import { afterEach, expect, test } from 'bun:test'; import { POST } from '../src/routes/api/sync/cancel/+server'; const originalEnv = { APP_MODE: process.env.APP_MODE, APP_ORIGIN: process.env.APP_ORIGIN, APP_CAPABILITY_ALLOWLIST: process.env.APP_CAPABILITY_ALLOWLIST }; afterEach(() => { for (const [key, value] of Object.entries(originalEnv)) { if (value === undefined) delete process.env[key]; else process.env[key] = value; } }); function event(request: Request): Parameters[0] { return { request, url: new URL(request.url), cookies: { get: () => undefined } as any, getClientAddress: () => '127.0.0.1' } as Parameters[0]; } test('sync cancellation rejects hostile origins before session or body work', async () => { process.env.APP_MODE = 'live'; process.env.APP_ORIGIN = 'http://localhost:5173'; process.env.APP_CAPABILITY_ALLOWLIST = 'asset_sync'; await expect(POST(event(new Request('http://localhost:5173/api/sync/cancel', { method: 'POST', headers: { origin: 'https://evil.example', 'content-type': 'application/json' }, body: '{}' })))).rejects.toMatchObject({ status: 403 }); }); test('sync cancellation returns unauthenticated before reading a request body', async () => { process.env.APP_MODE = 'live'; process.env.APP_ORIGIN = 'http://localhost:5173'; process.env.APP_CAPABILITY_ALLOWLIST = 'asset_sync'; const response = await POST(event(new Request('http://localhost:5173/api/sync/cancel', { method: 'POST', headers: { origin: 'http://localhost:5173', 'content-type': 'application/json' }, body: '{}' }))); expect(response.status).toBe(401); }); test('sync cancellation applies the bounded JSON byte cap', async () => { process.env.APP_MODE = 'demo'; process.env.APP_ORIGIN = 'http://localhost:5173'; process.env.APP_CAPABILITY_ALLOWLIST = 'asset_sync'; const response = POST(event(new Request('http://localhost:5173/api/sync/cancel', { method: 'POST', headers: { origin: 'http://localhost:5173', 'content-type': 'application/json' }, body: JSON.stringify({ jobId: 'x'.repeat(17_000) }) }))); await expect(response).rejects.toMatchObject({ status: 413 }); });