Skip to content

Commit 2390586

Browse files
committed
Merge remote-tracking branch 'origin/staging' into integrations-faq-geo
# Conflicts: # apps/sim/lib/integrations/integrations.json
2 parents 07e7aad + 5ab6d0d commit 2390586

93 files changed

Lines changed: 6974 additions & 428 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/components/icons.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2261,6 +2261,17 @@ export function BrandfetchIcon(props: SVGProps<SVGSVGElement>) {
22612261
)
22622262
}
22632263

2264+
export function BrexIcon(props: SVGProps<SVGSVGElement>) {
2265+
return (
2266+
<svg {...props} viewBox='0 0 223 179.3' fill='none' xmlns='http://www.w3.org/2000/svg'>
2267+
<path
2268+
fill='#FFFFFF'
2269+
d='M144.9,14.3c-8.7,11.6-10.8,15.5-19.2,15.5H0v149.4h49.3c11.1,0,21.9-5.4,28.9-14.3c9-12,10.2-15.5,18.9-15.5 H223V0h-49.6C162.3,0,151.5,5.4,144.9,14.3L144.9,14.3z M183.9,110.9h-52.6c-11.4,0-21.9,4.8-28.9,14c-9,12-10.8,15.5-19.2,15.5 H38.8V68.7h52.6c11.4,0,21.9-5.4,28.9-14.3c9-11.6,11.4-15.2,19.5-15.2h44.2V110.9z'
2270+
/>
2271+
</svg>
2272+
)
2273+
}
2274+
22642275
export function BrightDataIcon(props: SVGProps<SVGSVGElement>) {
22652276
return (
22662277
<svg

apps/docs/components/ui/icon-mapping.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
BoxCompanyIcon,
2525
BrainIcon,
2626
BrandfetchIcon,
27+
BrexIcon,
2728
BrightDataIcon,
2829
BrowserUseIcon,
2930
CalComIcon,
@@ -243,6 +244,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
243244
azure_devops: AzureIcon,
244245
box: BoxCompanyIcon,
245246
brandfetch: BrandfetchIcon,
247+
brex: BrexIcon,
246248
brightdata: BrightDataIcon,
247249
browser_use: BrowserUseIcon,
248250
calcom: CalComIcon,

apps/docs/content/docs/en/integrations/brex.mdx

Lines changed: 895 additions & 0 deletions
Large diffs are not rendered by default.

apps/docs/content/docs/en/integrations/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"azure_devops",
2222
"box",
2323
"brandfetch",
24+
"brex",
2425
"brightdata",
2526
"browser_use",
2627
"calcom",

apps/docs/content/docs/en/platform/costs.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,9 @@ By default, your usage is capped at the credits included in your plan. To allow
317317
| **Free** | 1 ||
318318
| **Pro** | Up to 3 ||
319319
| **Max** | Up to 10 ||
320-
| **Team / Enterprise** | Unlimited | Unlimited |
320+
| **Team / Enterprise** | | Unlimited (Owners and Admins) |
321321

322-
Team and Enterprise plans unlock shared workspaces that belong to your organization. Internal members invited to a shared workspace join the organization and count toward your seat total. Existing Sim users who already belong to another organization can be added as external workspace members; they get workspace access without joining your organization or using one of your seats. When a Team or Enterprise subscription is cancelled or downgraded, existing shared workspaces remain accessible to current members but new invites are disabled until the organization is upgraded again.
322+
Team and Enterprise plans unlock shared workspaces that belong to your organization. Every workspace created under a Team or Enterprise plan is organization-owned: Owners and Admins can create unlimited shared workspaces, while organization Members cannot create workspaces (personal workspaces created before joining the organization remain accessible). Internal members invited to a shared workspace join the organization and count toward your seat total — Enterprise invites require an available seat at invite time, while Team plans add a seat automatically when the invitee accepts. Existing Sim users who already belong to another organization can be added as external workspace members; they get workspace access without joining your organization or using one of your seats. When a Team or Enterprise subscription is cancelled or downgraded, existing shared workspaces remain accessible to current members but new invites are disabled until the organization is upgraded again.
323323

324324
### Rate Limits
325325

apps/docs/content/docs/en/platform/permissions.mdx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ Sim has two kinds of workspaces:
2323
| **Free** | 1 ||
2424
| **Pro** | Up to 3 ||
2525
| **Max** | Up to 10 ||
26-
| **Team / Enterprise** | Unlimited | Unlimited (seat-gated invites) |
26+
| **Team / Enterprise** || Unlimited (Owners and Admins) |
27+
28+
On Team and Enterprise plans, every workspace you create belongs to the organization. Organization Owners and Admins can create unlimited shared workspaces; organization Members cannot create workspaces. Personal workspaces created before joining the organization remain accessible. Enterprise invites require an available seat at invite time; on Team plans, a seat is added automatically when the invitee accepts.
2729

2830
<Callout type="info">
2931
When a Team or Enterprise subscription is cancelled or downgraded, existing shared workspaces stay accessible to current members. New invitations are blocked until the organization is upgraded again.

apps/realtime/src/database/operations.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { AuditAction, AuditResourceType, recordAudit } from '@sim/audit'
22
import * as schema from '@sim/db'
3-
import { workflow, workflowBlocks, workflowEdges, workflowSubflows } from '@sim/db'
3+
import {
4+
instrumentPoolClient,
5+
workflow,
6+
workflowBlocks,
7+
workflowEdges,
8+
workflowSubflows,
9+
} from '@sim/db'
410
import { createLogger } from '@sim/logger'
511
import {
612
BLOCK_OPERATIONS,
@@ -27,13 +33,16 @@ const logger = createLogger('SocketDatabase')
2733

2834
const connectionString = env.DATABASE_URL
2935
const socketDb = drizzle(
30-
postgres(connectionString, {
31-
prepare: false,
32-
idle_timeout: 10,
33-
connect_timeout: 20,
34-
max: 15,
35-
onnotice: () => {},
36-
}),
36+
instrumentPoolClient(
37+
postgres(connectionString, {
38+
prepare: false,
39+
idle_timeout: 10,
40+
connect_timeout: 20,
41+
max: 15,
42+
onnotice: () => {},
43+
}),
44+
'socketDb'
45+
),
3746
{ schema }
3847
)
3948

apps/realtime/src/handlers/subblocks.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export function setupSubblocksHandlers(socket: AuthenticatedSocket, roomManager:
130130
socket.emit('operation-failed', {
131131
operationId,
132132
error: 'User session not found',
133-
retryable: false,
133+
retryable: true,
134134
})
135135
}
136136
return
@@ -250,7 +250,7 @@ async function flushSubblockUpdate(
250250
io.to(socketId).emit('operation-failed', {
251251
operationId: opId,
252252
error: 'Workflow not found',
253-
retryable: false,
253+
retryable: true,
254254
})
255255
})
256256
return
@@ -352,7 +352,7 @@ async function flushSubblockUpdate(
352352
io.to(socketId).emit('operation-failed', {
353353
operationId: opId,
354354
error: 'Block no longer exists',
355-
retryable: false,
355+
retryable: true,
356356
})
357357
})
358358
}

apps/realtime/src/handlers/variables.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export function setupVariablesHandlers(socket: AuthenticatedSocket, roomManager:
118118
socket.emit('operation-failed', {
119119
operationId,
120120
error: 'User session not found',
121-
retryable: false,
121+
retryable: true,
122122
})
123123
}
124124
return
@@ -236,7 +236,7 @@ async function flushVariableUpdate(
236236
io.to(socketId).emit('operation-failed', {
237237
operationId: opId,
238238
error: 'Workflow not found',
239-
retryable: false,
239+
retryable: true,
240240
})
241241
})
242242
return
@@ -318,7 +318,7 @@ async function flushVariableUpdate(
318318
io.to(socketId).emit('operation-failed', {
319319
operationId: opId,
320320
error: 'Variable no longer exists',
321-
retryable: false,
321+
retryable: true,
322322
})
323323
})
324324
}

apps/realtime/src/middleware/permissions.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ export function checkRolePermission(
8383
return { allowed: true }
8484
}
8585

86+
/**
87+
* Verifies a user's access to a workflow via workspace permissions.
88+
*
89+
* Returns `hasAccess: false` only for genuine denials (workflow missing/archived
90+
* or no workspace permission). Transient failures (DB errors) are rethrown so the
91+
* caller can report them as retryable instead of a permanent access denial.
92+
*/
8693
export async function verifyWorkflowAccess(
8794
userId: string,
8895
workflowId: string
@@ -129,6 +136,6 @@ export async function verifyWorkflowAccess(
129136
`Error verifying workflow access for user ${userId}, workflow ${workflowId}:`,
130137
error
131138
)
132-
return { hasAccess: false }
139+
throw error
133140
}
134141
}

0 commit comments

Comments
 (0)