Skip to content

Commit 044937b

Browse files
committed
chore(mship): revert the credential-continue questions flow
Reverts #6385. Companion revert in mothership (#414).
1 parent cb8338c commit 044937b

38 files changed

Lines changed: 336 additions & 2925 deletions

apps/desktop/src/main/handoff.test.ts

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@ import {
88
buildRedeemScript,
99
type ConnectHandoffCallback,
1010
createAuthFlow,
11-
createConnectFlow,
1211
createHandoffManager,
1312
type HandoffCallback,
1413
type HandoffCallbacks,
15-
type HandoffManager,
1614
type HandoffManagerDeps,
1715
} from '@/main/handoff'
1816
import type { EventRecorder } from '@/main/observability'
@@ -243,24 +241,6 @@ describe('createHandoffManager', () => {
243241
expect(manager.consume(state, 'login')).toBe(false)
244242
expect(manager.consume(state, 'connect')).toBe(true)
245243
})
246-
247-
it('returns the chat attempt correlated with the accepted connect state', async () => {
248-
const deps = makeDeps()
249-
const manager = createHandoffManager(deps, makeCallbacks())
250-
await manager.beginConnect('google-email', {
251-
workspaceId: 'workspace-1',
252-
chatAttemptId: 'attempt-1',
253-
})
254-
const state = new URL(vi.mocked(deps.openExternal).mock.calls[0][0]).searchParams.get(
255-
'state'
256-
) as string
257-
258-
expect(manager.consumeConnect(state)).toEqual({
259-
workspaceId: 'workspace-1',
260-
chatAttemptId: 'attempt-1',
261-
})
262-
expect(manager.consumeConnect(state)).toBeNull()
263-
})
264244
})
265245

266246
describe('connect handoff account pinning', () => {
@@ -293,50 +273,6 @@ describe('connect handoff account pinning', () => {
293273
})
294274
})
295275

296-
describe('connect completion correlation', () => {
297-
function makeConnectManager(scope: { chatAttemptId?: string }): HandoffManager {
298-
return {
299-
begin: vi.fn(async () => true),
300-
beginConnect: vi.fn(async () => true),
301-
consume: vi.fn(() => true),
302-
consumeConnect: vi.fn(() => scope),
303-
clear: vi.fn(),
304-
}
305-
}
306-
307-
it('echoes the accepted handoff chat attempt to the renderer', () => {
308-
const notifyRenderer = vi.fn()
309-
const flow = createConnectFlow({
310-
handoff: makeConnectManager({ chatAttemptId: 'attempt-1' }),
311-
events: makeEvents(),
312-
focusMainWindow: vi.fn(),
313-
notifyRenderer,
314-
})
315-
316-
flow.handleCallback({ state: VALID_STATE })
317-
318-
expect(notifyRenderer).toHaveBeenCalledWith({ ok: true, chatAttemptId: 'attempt-1' })
319-
})
320-
321-
it('marks ordinary integrations-page completions as explicitly uncorrelated', () => {
322-
const notifyRenderer = vi.fn()
323-
const flow = createConnectFlow({
324-
handoff: makeConnectManager({}),
325-
events: makeEvents(),
326-
focusMainWindow: vi.fn(),
327-
notifyRenderer,
328-
})
329-
330-
flow.handleCallback({ state: VALID_STATE, error: 'oauth_failed' })
331-
332-
expect(notifyRenderer).toHaveBeenCalledWith({
333-
ok: false,
334-
error: 'oauth_failed',
335-
chatAttemptId: null,
336-
})
337-
})
338-
})
339-
340276
describe('createAuthFlow window failures', () => {
341277
function makeAuthDeps(ensureMainWindow: () => Promise<never>) {
342278
const events = makeEvents()

apps/desktop/src/main/handoff.ts

Lines changed: 24 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,12 @@ export interface HandoffManagerDeps {
6767
export interface ConnectScope {
6868
workspaceId?: string
6969
credentialId?: string
70-
chatAttemptId?: string
7170
}
7271

7372
export interface HandoffManager {
7473
begin(): Promise<boolean>
7574
beginConnect(providerId: string, scope?: ConnectScope): Promise<boolean>
7675
consume(state: string, kind: HandoffKind): boolean
77-
consumeConnect(state: string): ConnectScope | null
7876
clear(): void
7977
}
8078

@@ -94,12 +92,7 @@ export function createHandoffManager(
9492
const now = deps.now ?? Date.now
9593
let loopbackServer: Server | null = null
9694
let loopbackTimer: NodeJS.Timeout | undefined
97-
let pending: {
98-
state: string
99-
createdAt: number
100-
kind: HandoffKind
101-
connectScope?: ConnectScope
102-
} | null = null
95+
let pending: { state: string; createdAt: number; kind: HandoffKind } | null = null
10396

10497
const stopLoopback = () => {
10598
clearTimeout(loopbackTimer)
@@ -221,23 +214,10 @@ export function createHandoffManager(
221214
pending = null
222215
}
223216

224-
const consumePending = (state: string, kind: HandoffKind): NonNullable<typeof pending> | null => {
225-
if (!pending || pending.kind !== kind) return null
226-
if (now() - pending.createdAt > HANDOFF_TTL_MS) {
227-
clear()
228-
return null
229-
}
230-
if (!safeCompare(pending.state, state)) return null
231-
const consumed = pending
232-
clear()
233-
return consumed
234-
}
235-
236217
const beginFlow = async (
237218
kind: HandoffKind,
238219
landingPath: string,
239-
params: Record<string, string>,
240-
connectScope?: ConnectScope
220+
params: Record<string, string>
241221
): Promise<boolean> => {
242222
const state = generateShortId(STATE_LENGTH)
243223
// startLoopback() already tore down any prior server; if this bind fails,
@@ -248,12 +228,7 @@ export function createHandoffManager(
248228
clear()
249229
return false
250230
}
251-
pending = {
252-
state,
253-
createdAt: now(),
254-
kind,
255-
...(connectScope ? { connectScope: { ...connectScope } } : {}),
256-
}
231+
pending = { state, createdAt: now(), kind }
257232
const landing = new URL(landingPath, deps.origin())
258233
for (const [key, value] of Object.entries(params)) {
259234
landing.searchParams.set(key, value)
@@ -284,24 +259,26 @@ export function createHandoffManager(
284259
// unknown (offline, signed out): the page then falls back to its normal
285260
// login redirect rather than blocking a connect on a failed probe.
286261
const userId = await deps.currentUserId()
287-
return beginFlow(
288-
'connect',
289-
'/desktop/connect',
290-
{
291-
provider: providerId,
292-
...(userId ? { user: userId } : {}),
293-
...(scope.workspaceId ? { workspaceId: scope.workspaceId } : {}),
294-
...(scope.credentialId ? { credentialId: scope.credentialId } : {}),
295-
},
296-
scope
297-
)
262+
return beginFlow('connect', '/desktop/connect', {
263+
provider: providerId,
264+
...(userId ? { user: userId } : {}),
265+
...(scope.workspaceId ? { workspaceId: scope.workspaceId } : {}),
266+
...(scope.credentialId ? { credentialId: scope.credentialId } : {}),
267+
})
298268
},
299269
consume(state: string, kind: HandoffKind) {
300-
return consumePending(state, kind) !== null
301-
},
302-
consumeConnect(state: string) {
303-
const consumed = consumePending(state, 'connect')
304-
return consumed ? { ...(consumed.connectScope ?? {}) } : null
270+
if (!pending || pending.kind !== kind) {
271+
return false
272+
}
273+
if (now() - pending.createdAt > HANDOFF_TTL_MS) {
274+
clear()
275+
return false
276+
}
277+
if (!safeCompare(pending.state, state)) {
278+
return false
279+
}
280+
clear()
281+
return true
305282
},
306283
clear,
307284
}
@@ -466,8 +443,6 @@ export function createAuthFlow(deps: AuthFlowDeps): AuthFlow {
466443
export interface ConnectHandoffResult {
467444
ok: boolean
468445
error?: string
469-
/** Exact Mothership chat attempt, or null for ordinary integration flows. */
470-
chatAttemptId: string | null
471446
}
472447

473448
export interface ConnectFlowDeps {
@@ -501,24 +476,19 @@ export function createConnectFlow(deps: ConnectFlowDeps): ConnectFlow {
501476
return opened
502477
},
503478
handleCallback(callback: ConnectHandoffCallback) {
504-
const scope = deps.handoff.consumeConnect(callback.state)
505-
if (!scope) {
479+
if (!deps.handoff.consume(callback.state, 'connect')) {
506480
deps.events.record('connect_handoff_state_fail')
507481
return
508482
}
509483
if (callback.error === undefined) {
510484
deps.events.record('connect_handoff_ok')
511485
deps.focusMainWindow()
512-
deps.notifyRenderer({ ok: true, chatAttemptId: scope.chatAttemptId ?? null })
486+
deps.notifyRenderer({ ok: true })
513487
return
514488
}
515489
deps.events.record('connect_handoff_error', { error: callback.error })
516490
deps.focusMainWindow()
517-
deps.notifyRenderer({
518-
ok: false,
519-
error: callback.error,
520-
chatAttemptId: scope.chatAttemptId ?? null,
521-
})
491+
deps.notifyRenderer({ ok: false, error: callback.error })
522492
},
523493
}
524494
}

apps/desktop/src/main/ipc.test.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -337,20 +337,14 @@ describe('registerIpcHandlers', () => {
337337

338338
// Chip-initiated connects carry workspace/credential scope; malformed
339339
// scopes (wrong types, unsafe ids) are rejected before the handoff.
340-
expect(
341-
await handler?.(appEvent, 'slack', {
342-
workspaceId: 'ws1',
343-
credentialId: 'cred_1',
344-
chatAttemptId: 'attempt_1',
345-
})
346-
).toBe(true)
340+
expect(await handler?.(appEvent, 'slack', { workspaceId: 'ws1', credentialId: 'cred_1' })).toBe(
341+
true
342+
)
347343
expect(deps.beginOAuthConnect).toHaveBeenCalledWith('slack', {
348344
workspaceId: 'ws1',
349345
credentialId: 'cred_1',
350-
chatAttemptId: 'attempt_1',
351346
})
352347
expect(await handler?.(appEvent, 'slack', { workspaceId: 'ws/../evil' })).toBe(false)
353-
expect(await handler?.(appEvent, 'slack', { chatAttemptId: '../wrong' })).toBe(false)
354348
expect(await handler?.(appEvent, 'slack', 'not-an-object')).toBe(false)
355349
})
356350

apps/desktop/src/main/ipc.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ function parseDesktopScope(raw: unknown): string | null {
9090
export interface OAuthConnectScope {
9191
workspaceId?: string
9292
credentialId?: string
93-
chatAttemptId?: string
9493
}
9594

9695
/**
@@ -105,11 +104,7 @@ export function parseOAuthConnectScope(raw: unknown): OAuthConnectScope | undefi
105104
if (typeof raw !== 'object') {
106105
return undefined
107106
}
108-
const { workspaceId, credentialId, chatAttemptId } = raw as {
109-
workspaceId?: unknown
110-
credentialId?: unknown
111-
chatAttemptId?: unknown
112-
}
107+
const { workspaceId, credentialId } = raw as { workspaceId?: unknown; credentialId?: unknown }
113108
if (
114109
workspaceId !== undefined &&
115110
(typeof workspaceId !== 'string' || !ID_PATTERN.test(workspaceId))
@@ -122,16 +117,9 @@ export function parseOAuthConnectScope(raw: unknown): OAuthConnectScope | undefi
122117
) {
123118
return undefined
124119
}
125-
if (
126-
chatAttemptId !== undefined &&
127-
(typeof chatAttemptId !== 'string' || !ID_PATTERN.test(chatAttemptId))
128-
) {
129-
return undefined
130-
}
131120
return {
132121
...(workspaceId !== undefined ? { workspaceId } : {}),
133122
...(credentialId !== undefined ? { credentialId } : {}),
134-
...(chatAttemptId !== undefined ? { chatAttemptId } : {}),
135123
}
136124
}
137125

apps/sim/app/api/auth/trello/authorize/route.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { parseRequest } from '@/lib/api/server'
66
import { getSession } from '@/lib/auth'
77
import { env } from '@/lib/core/config/env'
88
import { getBaseUrl } from '@/lib/core/utils/urls'
9-
import { isSameOrigin } from '@/lib/core/utils/validation'
109
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
1110
import { getCanonicalScopesForProvider } from '@/lib/oauth/utils'
1211

@@ -15,7 +14,6 @@ const logger = createLogger('TrelloAuthorize')
1514
export const dynamic = 'force-dynamic'
1615

1716
const TRELLO_STATE_COOKIE = 'trello_oauth_state'
18-
const TRELLO_RETURN_URL_COOKIE = 'trello_return_url'
1917
const TRELLO_STATE_COOKIE_PATH = '/api/auth/trello'
2018
const TRELLO_STATE_COOKIE_MAX_AGE_SECONDS = 60 * 10
2119

@@ -28,7 +26,6 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
2826

2927
const parsed = await parseRequest(authorizeTrelloContract, request, {})
3028
if (!parsed.success) return parsed.response
31-
const { returnUrl: requestedReturnUrl } = parsed.data.query
3229

3330
const apiKey = env.TRELLO_API_KEY
3431

@@ -60,20 +57,6 @@ export const GET = withRouteHandler(async (request: NextRequest) => {
6057
maxAge: TRELLO_STATE_COOKIE_MAX_AGE_SECONDS,
6158
path: TRELLO_STATE_COOKIE_PATH,
6259
})
63-
if (requestedReturnUrl && isSameOrigin(requestedReturnUrl)) {
64-
response.cookies.set(TRELLO_RETURN_URL_COOKIE, requestedReturnUrl, {
65-
httpOnly: true,
66-
secure: process.env.NODE_ENV === 'production',
67-
sameSite: 'lax',
68-
maxAge: TRELLO_STATE_COOKIE_MAX_AGE_SECONDS,
69-
path: TRELLO_STATE_COOKIE_PATH,
70-
})
71-
} else {
72-
response.cookies.delete({
73-
name: TRELLO_RETURN_URL_COOKIE,
74-
path: TRELLO_STATE_COOKIE_PATH,
75-
})
76-
}
7760
return response
7861
} catch (error) {
7962
logger.error('Error initiating Trello authorization:', error)

0 commit comments

Comments
 (0)