import { describe, expect, test } from 'bun:test' import { Buffer } from 'node:buffer' import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' function runtimeToken(workspaceId = 'workspace-id'): string { const payload = Buffer.from(JSON.stringify({ workspace: { id: workspaceId, title: 'Workspace' } })).toString('base64url') return `header.${payload}.signature` } describe('hosted runtime configuration', () => { test('uses the injected credential and URLs without a local session', () => { const token = runtimeToken('runtime-workspace-id') const script = ` import { apiRequest, getApiBaseUrl, getAppBaseUrl, getAuthenticatedWorkspaceId, loadApiKey } from './skill/common.ts' let requestUrl = '' let requestHeaders = {} globalThis.fetch = async (url, init) => { requestUrl = String(url) requestHeaders = Object.fromEntries(new Headers(init?.headers)) return new Response(JSON.stringify({ id: 'project-id' }), { status: 200, headers: { 'Content-Type': 'application/json' }, }) } await apiRequest('/project') console.log(JSON.stringify({ token: loadApiKey(), workspaceId: getAuthenticatedWorkspaceId(), apiUrl: getApiBaseUrl(), appUrl: getAppBaseUrl(), requestUrl, requestHeaders, })) ` const result = Bun.spawnSync({ cmd: [process.execPath, '-e', script], cwd: join(import.meta.dir, '..'), env: { ...process.env, DATA_TOKEN: ` ${token} `, TELA_API_URL: ' https://runtime-api.example.com ', TELA_APP_URL: ' https://runtime-app.example.com ', }, stderr: 'pipe', stdout: 'pipe', }) expect(result.exitCode).toBe(0) expect(result.stderr.toString()).toBe('') const output = JSON.parse(result.stdout.toString()) as { token: string workspaceId: string apiUrl: string appUrl: string requestUrl: string requestHeaders: Record } expect(output).toEqual({ token, workspaceId: 'runtime-workspace-id', apiUrl: 'https://runtime-api.example.com', appUrl: 'https://runtime-app.example.com', requestUrl: 'https://runtime-api.example.com/project', requestHeaders: { 'content-type': 'application/json', 'x-data-token': token, }, }) }) test('derives the staging app URL from the hosted API URL', () => { const result = Bun.spawnSync({ cmd: [process.execPath, '-e', ` import { getAppBaseUrl } from './skill/common.ts' console.log(getAppBaseUrl()) `], cwd: join(import.meta.dir, '..'), env: { ...process.env, TELA_API_URL: 'https://api.telastaging.com', TELA_APP_URL: '', }, stderr: 'pipe', stdout: 'pipe', }) expect(result.exitCode).toBe(0) expect(result.stderr.toString()).toBe('') expect(result.stdout.toString().trim()).toBe('https://app.telastaging.com') }) }) describe('device-flow sessions', () => { function applicationToken(expiresInSeconds: number): string { const exp = Math.floor(Date.now() / 1000) + expiresInSeconds const payload = Buffer.from(JSON.stringify({ token_type: 'application', exp, workspace: { id: 'workspace-id', title: 'Workspace' } })).toString('base64url') return `header.${payload}.signature` } function runWithSession(session: string, script: string) { const home = mkdtempSync(join(tmpdir(), 'tela-skills-session-')) mkdirSync(join(home, '.tela')) const sessionPath = join(home, '.tela', 'session.production') writeFileSync(sessionPath, session) const result = Bun.spawnSync({ cmd: [process.execPath, '-e', script], cwd: join(import.meta.dir, '..'), env: { ...process.env, HOME: home, DATA_TOKEN: '', TELA_API_URL: 'https://api.example.com' }, stderr: 'pipe', stdout: 'pipe', }) expect(result.stderr.toString()).toBe('') expect(result.exitCode).toBe(0) return { sessionPath, output: JSON.parse(result.stdout.toString()) } } const captureRequests = ` import { apiRequest, loadApiKey } from './skill/common.ts' const calls = [] globalThis.fetch = async (url, init) => { calls.push({ url: String(url), method: init?.method ?? 'GET', headers: Object.fromEntries(new Headers(init?.headers)) }) const body = String(url).includes('/token/refresh') ? { data: { accessToken: process.env.REFRESHED_TOKEN, refreshToken: 'refresh-2' } } : {} return new Response(JSON.stringify(body), { status: 200, headers: { 'Content-Type': 'application/json' } }) } await apiRequest('/project') console.log(JSON.stringify({ token: loadApiKey(), calls })) ` test('sends a device-flow access token as a Bearer credential', () => { const accessToken = applicationToken(600) const { output } = runWithSession(JSON.stringify({ accessToken, refreshToken: 'refresh-1', authApiUrl: 'https://auth.example.com', }), captureRequests) expect(output.token).toBe(accessToken) expect(output.calls).toHaveLength(1) expect(output.calls[0].url).toBe('https://api.example.com/project') expect(output.calls[0].headers.authorization).toBe(`Bearer ${accessToken}`) expect(output.calls[0].headers['x-data-token']).toBeUndefined() }) test('keeps sending legacy data tokens in the x-data-token header', () => { const dataToken = `header.${Buffer.from(JSON.stringify({ workspace: { id: 'workspace-id', title: 'Workspace' } })).toString('base64url')}.signature` const { output } = runWithSession(dataToken, captureRequests) expect(output.token).toBe(dataToken) expect(output.calls[0].headers['x-data-token']).toBe(dataToken) expect(output.calls[0].headers.authorization).toBeUndefined() }) test('shares one refresh between concurrent calls', () => { const refreshedToken = applicationToken(900) process.env.REFRESHED_TOKEN = refreshedToken const { output } = runWithSession(JSON.stringify({ accessToken: applicationToken(30), refreshToken: 'refresh-1', authApiUrl: 'https://auth.example.com', }), captureRequests.replace(`await apiRequest('/project')`, `await Promise.all([apiRequest('/project'), apiRequest('/project'), apiRequest('/project')])`)) const refreshCalls = output.calls.filter((call: { url: string }) => call.url.includes('/token/refresh')) expect(refreshCalls).toHaveLength(1) expect(output.calls).toHaveLength(4) expect(output.token).toBe(refreshedToken) }) test('refreshes an expiring device-flow session before calling the API', () => { const expiringToken = applicationToken(30) const refreshedToken = applicationToken(900) process.env.REFRESHED_TOKEN = refreshedToken const { sessionPath, output } = runWithSession(JSON.stringify({ accessToken: expiringToken, refreshToken: 'refresh-1', authApiUrl: 'https://auth.example.com', }), captureRequests) expect(output.calls.map((call: { url: string }) => call.url)).toEqual([ 'https://auth.example.com/api/auth/applications/token/refresh', 'https://api.example.com/project', ]) expect(output.calls[0].method).toBe('POST') expect(output.calls[0].headers['x-tela-refresh-token']).toBe('refresh-1') expect(output.calls[1].headers.authorization).toBe(`Bearer ${refreshedToken}`) expect(output.token).toBe(refreshedToken) const saved = JSON.parse(readFileSync(sessionPath, 'utf-8')) expect(saved.accessToken).toBe(refreshedToken) expect(saved.refreshToken).toBe('refresh-2') expect(saved.authApiUrl).toBe('https://auth.example.com') }) })