Skip to content

Commit 1bb3c4f

Browse files
committed
Merge remote-tracking branch 'origin/staging' into improvement/org-view
# Conflicts: # apps/sim/app/o/[organizationId]/integrations/account-actions-menu.tsx # apps/sim/app/o/[organizationId]/integrations/assistant-account-integrations.tsx # apps/sim/ee/credential-groups/components/organization-person-connections.tsx # apps/sim/lib/assistant-actions/application/review.ts # apps/sim/platform/app/(shell)/integrations/_components/connected-credential/connected-credential.tsx # apps/sim/scripts/test-org-redesign-e2e.ts
2 parents 8659c05 + 79dbf14 commit 1bb3c4f

79 files changed

Lines changed: 34565 additions & 325 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/search/connect-your-account.mdx‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,25 @@ After your admin adds a source in **Settings → Sources**, connect your own acc
1010
## Connect and verify
1111

1212
1. Join the Sim organization through its invitation or SSO. Use the verified email required by the provider connection.
13-
2. Open **Integrations**, select the app, and choose **Connect** in its header.
14-
3. Complete authorization in the new tab. If the popup is blocked, allow it and select **Connect** again.
13+
2. Open **Integrations**, select the app, and choose the app's button under **Connect your account**.
14+
3. Complete authorization in the new tab. If the popup is blocked, allow it and select the button again.
1515
4. Return to **Search** or **Search → Assistant** and search for content your account can open. Read a result and follow its source link.
1616

1717
<Image
1818
src="/static/search/connect-account-details.png"
19-
alt="Coda integration details with Connect in the resource header and no account connected"
19+
alt="Coda integration details with a connect button and no account connected"
2020
width={1440}
2121
height={1000}
2222
variant="overview"
2323
/>
2424

25-
Your organization currently supports one connected account per provider. Open the app to see that account's permissions and connection actions.
25+
To connect another account of the same app, such as Google Drive for two different work accounts, open the app and choose **Add account**, then pick the other account when the provider asks. You can connect up to five accounts per app, and Search looks across all of them. Open an account to see its tool permissions when the app supports them; each account's menu has **Reconnect** and **Disconnect**.
26+
27+
- Slack accounts must belong to your organization's connected workspace.
28+
- Zoom, Lucid, and Databricks allow one account, because Sim cannot yet tell their accounts apart.
29+
- If the provider signs you straight back into a connected account, sign in to the other account with the provider first, then choose **Add account** again.
30+
31+
Reconnecting keeps the same account. To use a different one, add it as a new account or disconnect the old one first. If Sim asks you to reconnect before adding another account, it could not confirm which account an existing connection belongs to. Reconnect that one, then add the other. Your organization and the provider must allow each account to authorize Sim.
2632

2733
The connection is usable when authorization completes; no initial indexing run is required. If a provider is missing, ask an admin to add it in **Sources**. `Not configured` means its app or deployment setup needs an admin's attention.
2834

@@ -33,7 +39,7 @@ You do not choose repositories, channels, labels, or an indexing method during p
3339
| Source setup | Personal connection |
3440
| --- | --- |
3541
| **Member accounts** | Connect your own provider account. |
36-
| **GitHub App** | Connect GitHub once per Sim organization. Each selected repository must be readable by you and the installation. |
42+
| **GitHub App** | Connect one or more GitHub accounts. Each selected repository must be readable by you and the installation. |
3743
| Google service account: Gmail, Calendar, Drive | Connect each corresponding Google service. The source verifies your identity and resource access through delegation. |
3844
| Confluence service account | Connect Confluence. Both your account and the service connection must read the selected content. |
3945
| Coda | Connect personal Coda MCP. Service mode also verifies the parent document with its REST token. |
@@ -46,7 +52,7 @@ Creating Jira sprints requires the Jira sprint permission. If your account was c
4652

4753
## Tool permissions
4854

49-
Open the app in **Integrations** and select your account. Tool permissions appear in its details when the app has supported Assistant tools available to you. Hover over or focus the info button beside a tool to read its description. Set a preference for each operation or use the **Read-only tools** and **Write tools** group controls:
55+
Open the app in **Integrations**. If you connected several accounts, select one. Tool permissions appear in its details when the app has supported Assistant tools available to you. Hover over or focus the info button beside a tool to read its description. Set a preference for each operation or use the **Read-only tools** and **Write tools** group controls:
5056

5157
| Preference | Behavior |
5258
| --- | --- |

‎apps/sim/app/api/billing/update-cost/route.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ async function updateCostInner(req: NextRequest, span: Span): Promise<NextRespon
196196
const startTime = Date.now()
197197

198198
try {
199-
logger.info(`[${requestId}] Update cost request started`)
199+
logger.debug(`[${requestId}] Update cost request started`)
200200

201201
// Check authentication (internal API key)
202202
const authResult = checkInternalApiKey(req)
@@ -324,7 +324,7 @@ async function updateCostInner(req: NextRequest, span: Span): Promise<NextRespon
324324
...(idempotencyKey ? { [TraceAttr.BillingIdempotencyKey]: idempotencyKey } : {}),
325325
})
326326

327-
logger.info(`[${requestId}] Processing cost update`, {
327+
logger.debug(`[${requestId}] Processing cost update`, {
328328
userId,
329329
cost,
330330
model,
@@ -408,7 +408,7 @@ async function updateCostInner(req: NextRequest, span: Span): Promise<NextRespon
408408
}
409409
: undefined
410410

411-
logger.info(`[${requestId}] Billing payer resolved`, {
411+
logger.debug(`[${requestId}] Billing payer resolved`, {
412412
userId,
413413
billingProtocol: protocol,
414414
billingResolution: getBillingResolution(isMarkerlessLegacy, billingAttribution),
@@ -443,7 +443,10 @@ async function updateCostInner(req: NextRequest, span: Span): Promise<NextRespon
443443
const billed = result.billed
444444
logger.info(`[${requestId}] Cumulative cost top-up`, {
445445
userId,
446+
billingPayer: billingContext?.billingEntity ?? { type: 'user', id: userId },
447+
workspaceId: resolvedWorkspaceId,
446448
source,
449+
model,
447450
cumulativeCost: cost,
448451
billedDelta: result.delta,
449452
newTotal: result.total,

‎apps/sim/app/api/credential-groups/oauth-callback.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ export async function handleCredentialGroupOAuthCallback({
139139
: error instanceof CredentialGroupOAuthError && error.statusCode === 409
140140
? 'configuration_changed'
141141
: 'failed'
142+
if (error instanceof CredentialGroupOAuthError && error.failure) status = error.failure
142143
if (identityFailure) {
143144
switch (identityFailure.reason) {
144145
case 'email_unverified':

‎apps/sim/app/api/mcp/oauth/callback/route.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
} from '@/lib/credential-groups/mcp-oauth-state'
1919
import { CredentialGroupOAuthStateVersionError } from '@/lib/credential-groups/oauth-attempt-version'
2020
import type { CredentialGroupOAuthFailure } from '@/lib/credential-groups/oauth-completion'
21+
import { CredentialGroupOAuthError } from '@/lib/credential-groups/provider-adapter'
2122
import { enforcePublicCredentialGroupIpRateLimit } from '@/lib/credential-groups/rate-limit'
2223
import {
2324
assertSafeOauthServerUrl,
@@ -162,7 +163,9 @@ async function completeManagedMcpCallback(params: {
162163
})
163164
} catch (error) {
164165
logger.error('Managed MCP OAuth callback failed', error)
165-
return failureRedirect('failed')
166+
return failureRedirect(
167+
error instanceof CredentialGroupOAuthError && error.failure ? error.failure : 'failed'
168+
)
166169
}
167170
}
168171

‎apps/sim/app/credential-groups/enroll/[token]/page.tsx‎

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ export default async function CredentialGroupEnrollmentPage({
227227
)
228228
const visibleOptions = focusedOption ? [focusedOption] : activeOptions
229229
const focusedConnected =
230-
focusedOption?.connections[0]?.status === 'connected' &&
230+
focusedOption?.connections.some((connection) => connection.status === 'connected') &&
231231
(returnToSearch || connectedOptionId === focusedOption.id)
232232
const connectedOption = connectedOptionId
233233
? activeOptions.find((option) => option.id === connectedOptionId)
@@ -286,29 +286,34 @@ export default async function CredentialGroupEnrollmentPage({
286286
<div className='au:space-y-2'>
287287
{visibleOptions.map((option) => {
288288
const ProviderIcon = getCredentialGroupProviderService(option.provider).icon
289-
const connection = option.connections[0]
289+
const visibleConnections = option.connections.filter(
290+
(connection) => connection.status !== 'revoked'
291+
)
290292
return (
291293
<SettingsResourceRow
292294
key={option.id}
293295
icon={<ProviderIcon />}
294296
title={option.label}
295297
description={
296-
option.connections.length > 0
297-
? option.connections.map((account) => (
298-
<span key={account.email} className='au:block'>
298+
visibleConnections.length > 0
299+
? visibleConnections.map((account) => (
300+
<span key={`${account.email}-${account.grantedAt}`} className='au:block'>
299301
{account.email}
300302
{account.status === 'connected'
301303
? ' — Connected'
302-
: ' — Reconnect required'}
304+
: ' — Reconnect needed'}
303305
</span>
304306
))
305307
: 'Not connected'
306308
}
307309
actions={
308-
focusedConnected ? undefined : (
310+
focusedConnected &&
311+
visibleConnections.every(
312+
(account) => account.status === 'connected'
313+
) ? undefined : (
309314
<OAuthConnectLink
310315
href={`/api/credential-groups/enroll/${encodeURIComponent(token)}/oauth/${encodeURIComponent(option.id)}${focused ? `?returnTo=${returnToSearch ? 'search' : 'accounts'}` : ''}`}
311-
reconnect={Boolean(connection)}
316+
reconnect={visibleConnections.length > 0}
312317
variant={focused ? 'primary' : undefined}
313318
/>
314319
)
@@ -328,7 +333,7 @@ export default async function CredentialGroupEnrollmentPage({
328333
server.connection?.status === 'connected'
329334
? 'Connected'
330335
: server.connection
331-
? 'Reconnect required'
336+
? 'Reconnect needed'
332337
: server.description || 'Not connected'
333338
}
334339
actions={

‎apps/sim/app/ingest/[[...path]]/route.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe('PostHog ingest proxy', () => {
3131
const response = await POST(createIngestRequest(controller.signal))
3232

3333
expect(response.status).toBe(499)
34-
expect(logger.error).not.toHaveBeenCalled()
34+
expect(logger.warn).not.toHaveBeenCalled()
3535
})
3636

3737
it('reports an upstream failure while the client is still connected', async () => {
@@ -40,7 +40,7 @@ describe('PostHog ingest proxy', () => {
4040
const response = await POST(createIngestRequest())
4141

4242
expect(response.status).toBe(502)
43-
expect(logger.error).toHaveBeenCalledWith(
43+
expect(logger.warn).toHaveBeenCalledWith(
4444
'PostHog proxy error',
4545
expect.objectContaining({ error: 'The operation timed out.' })
4646
)

‎apps/sim/app/ingest/[[...path]]/route.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ async function handler(request: NextRequest) {
6161
logger.info('Client closed PostHog proxy request', { method: request.method })
6262
return new NextResponse(null, { status: 499 })
6363
}
64-
logger.error('PostHog proxy error', {
64+
logger.warn('PostHog proxy error', {
6565
url,
6666
method: request.method,
6767
error: toError(error).message,

‎apps/sim/background/webhook-execution.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ async function executeWebhookJobInternal(
11001100
}
11011101
}
11021102

1103-
logger.info(`[${requestId}] Executing workflow for ${payload.provider} webhook`)
1103+
logger.debug(`[${requestId}] Executing workflow for ${payload.provider} webhook`)
11041104

11051105
const metadata: ExecutionMetadata = {
11061106
requestId,

‎apps/sim/blocks/blocks/credential.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export const CredentialBlock: BlockConfig = {
2828
- Use the Provider filter to narrow results to specific services (e.g. Gmail, Slack).
2929
- Use "List Organization Accounts" with Providers selected and Email blank to discover all accessible accounts for those integrations.
3030
- Organization lists return one page at a time. While hasMore is true, pass nextCursor as Cursor with the same filters to get every matching account.
31-
- "Find Organization Account" requires an exact enrollment email and provider, and fails unless exactly one active account matches.
31+
- "Find Organization Account" requires an exact enrollment email and provider, and returns that person's first connected account for the provider, or fails if there is none. Use "List Organization Accounts" to reach their other accounts.
3232
- Outputs contain account identities and credential references, never secret values.
3333
- To switch credentials across environments, replace the single Credential block rather than updating every downstream block.
3434
`,

‎apps/sim/ee/credential-groups/person-connections.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function personConnectionSummaries(person: CredentialGroupEnrollmentDetai
3535
key: `mcp:${connection.mcpServerId}`,
3636
providerId: undefined,
3737
name: connection.name,
38-
count: 1,
38+
count: connection.count,
3939
icon: undefined,
4040
})),
4141
]

0 commit comments

Comments
 (0)