diff --git a/src/features/dashboard/terminal/dashboard-terminal.tsx b/src/features/dashboard/terminal/dashboard-terminal.tsx
index 3269dc675..cff03d0ff 100644
--- a/src/features/dashboard/terminal/dashboard-terminal.tsx
+++ b/src/features/dashboard/terminal/dashboard-terminal.tsx
@@ -4,6 +4,7 @@ import { Terminal as XTerm } from '@xterm/xterm'
import type Sandbox from 'e2b'
import type { CommandHandle } from 'e2b'
import { useCallback, useEffect, useRef, useState } from 'react'
+import type { SandboxManagementAuth } from '@/core/shared/sandbox-management-auth'
import {
DEFAULT_COLS,
DEFAULT_CWD,
@@ -38,7 +39,7 @@ interface DashboardTerminalProps {
initialCommand?: string
initialSandboxId?: string
initialTemplate?: string
- teamId: string
+ sandboxManagementAuth: SandboxManagementAuth
}
export default function DashboardTerminal({
@@ -46,7 +47,7 @@ export default function DashboardTerminal({
initialCommand = '',
initialSandboxId,
initialTemplate,
- teamId,
+ sandboxManagementAuth,
}: DashboardTerminalProps) {
const [status, setStatus] = useState('idle')
const [activeSandboxId, setActiveSandboxId] = useState()
@@ -200,8 +201,8 @@ export default function DashboardTerminal({
const { sandbox } = await openTerminalSandbox({
forceNewSandbox: options.forceNewSandbox,
onStatus: appendOutput,
+ sandboxManagementAuth,
sandboxId: options.sandboxId,
- teamId,
template: nextTemplate,
})
@@ -270,7 +271,7 @@ export default function DashboardTerminal({
disconnectTerminal,
resizeTerminal,
runCommand,
- teamId,
+ sandboxManagementAuth,
template,
updateTerminalUrl,
]
diff --git a/src/features/dashboard/terminal/sandbox-session.ts b/src/features/dashboard/terminal/sandbox-session.ts
index 2e6f86700..ea57015fc 100644
--- a/src/features/dashboard/terminal/sandbox-session.ts
+++ b/src/features/dashboard/terminal/sandbox-session.ts
@@ -1,6 +1,5 @@
import Sandbox from 'e2b'
-import { SUPABASE_AUTH_HEADERS } from '@/configs/api'
-import { supabase } from '@/core/shared/clients/supabase/client'
+import type { SandboxManagementAuth } from '@/core/shared/sandbox-management-auth'
import { TERMINAL_SANDBOX_TIMEOUT_MS } from './constants'
import {
clearStoredTerminalSession,
@@ -11,26 +10,19 @@ import {
interface OpenTerminalSandboxOptions {
forceNewSandbox?: boolean
onStatus: (message: string) => void
+ sandboxManagementAuth: SandboxManagementAuth
sandboxId?: string
- teamId: string
template: string
}
export async function openTerminalSandbox({
forceNewSandbox = false,
onStatus,
+ sandboxManagementAuth,
sandboxId,
- teamId,
template,
}: OpenTerminalSandboxOptions) {
- const { data } = await supabase.auth.getSession()
-
- if (!data.session) {
- throw new Error('You need to sign in before opening a terminal.')
- }
-
- const userId = data.session.user.id
- const headers = SUPABASE_AUTH_HEADERS(data.session.access_token, teamId)
+ const { headers, userId } = sandboxManagementAuth
if (sandboxId) {
onStatus(`Connecting to terminal sandbox ${sandboxId}...\r\n`)
@@ -100,8 +92,6 @@ function createTerminalSandbox({
template: string
userId: string
}) {
- // The browser SDK sends the signed-in user's Supabase token so E2B can
- // authorize sandbox ownership without a dashboard proxy endpoint.
return Sandbox.create(template, {
domain: process.env.NEXT_PUBLIC_E2B_DOMAIN,
timeoutMs: TERMINAL_SANDBOX_TIMEOUT_MS,
diff --git a/tests/unit/dashboard-terminal.test.ts b/tests/unit/dashboard-terminal.test.ts
index 54675e595..9b0d683da 100644
--- a/tests/unit/dashboard-terminal.test.ts
+++ b/tests/unit/dashboard-terminal.test.ts
@@ -13,13 +13,10 @@ import {
} from '@/features/dashboard/terminal/template'
import { calculateTerminalSize } from '@/features/dashboard/terminal/terminal-size'
-const { mockCreateSandbox, mockConnectSandbox, mockGetSession } = vi.hoisted(
- () => ({
- mockCreateSandbox: vi.fn(),
- mockConnectSandbox: vi.fn(),
- mockGetSession: vi.fn(),
- })
-)
+const { mockCreateSandbox, mockConnectSandbox } = vi.hoisted(() => ({
+ mockCreateSandbox: vi.fn(),
+ mockConnectSandbox: vi.fn(),
+}))
vi.mock('e2b', () => ({
default: {
@@ -28,14 +25,6 @@ vi.mock('e2b', () => ({
},
}))
-vi.mock('@/core/shared/clients/supabase/client', () => ({
- supabase: {
- auth: {
- getSession: mockGetSession,
- },
- },
-}))
-
function installLocalStorage() {
const values = new Map()
@@ -59,19 +48,17 @@ function installLocalStorage() {
}
describe('dashboard terminal helpers', () => {
+ const sandboxManagementAuth = {
+ headers: {
+ [SUPABASE_TOKEN_HEADER]: 'supabase-token',
+ [SUPABASE_TEAM_HEADER]: 'team-123',
+ },
+ userId: 'user-123',
+ }
+
beforeEach(() => {
vi.clearAllMocks()
installLocalStorage()
- mockGetSession.mockResolvedValue({
- data: {
- session: {
- access_token: 'supabase-token',
- user: {
- id: 'user-123',
- },
- },
- },
- })
mockCreateSandbox.mockResolvedValue({ sandboxId: 'created-sandbox' })
mockConnectSandbox.mockResolvedValue({ sandboxId: 'connected-sandbox' })
})
@@ -217,8 +204,8 @@ describe('dashboard terminal helpers', () => {
await openTerminalSandbox({
onStatus: (message) => statuses.push(message),
+ sandboxManagementAuth,
sandboxId: 'sandbox-from-url',
- teamId: 'team-123',
template: 'base',
})
@@ -240,7 +227,7 @@ describe('dashboard terminal helpers', () => {
it('creates and stores a terminal sandbox when no reusable session exists', async () => {
await openTerminalSandbox({
onStatus: vi.fn(),
- teamId: 'team-123',
+ sandboxManagementAuth,
template: 'base',
})
@@ -275,7 +262,7 @@ describe('dashboard terminal helpers', () => {
await openTerminalSandbox({
onStatus: vi.fn(),
- teamId: 'team-123',
+ sandboxManagementAuth,
template: 'base',
})