import { describe, it } from 'node:test'; import { strict as assert } from 'node:assert'; import * as fs from 'node:fs'; import * as net from 'node:net'; import * as os from 'node:os'; import * as path from 'node:path'; import type { ILoadedMatrixPackageEnvironment } from '../../src/utils/package-environment.js'; import type { IResolvedRunnerTransportPlan } from '../../src/utils/runner-transport.js'; import type { ILoadedMatrixWebappManifest } from '../../src/utils/webapp-manifest.js'; import { startStandaloneWebappServer } from '../../src/utils/standalone-webapp-server.js'; async function getAvailablePort(): Promise { const server = await new Promise((resolve, reject) => { const candidate = net.createServer(); candidate.once('error', reject); candidate.listen(0, '127.0.0.1', () => resolve(candidate)); }); const address = server.address(); assert.ok(address && typeof address === 'object'); const port = address.port; await new Promise((resolve, reject) => { server.close((error) => (error ? reject(error) : resolve())); }); return port; } describe('standalone webapp server', () => { it('advertises JWT browser auth when the runner transport uses credentialsRef', async () => { const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'standalone-webapp-server-')); const packageDir = path.join(tempRoot, 'package'); const distDir = path.join(packageDir, 'dist'); fs.mkdirSync(distDir, { recursive: true }); const httpPort = await getAvailablePort(); const credentialsPath = path.join(tempRoot, 'credentials.json'); fs.writeFileSync(credentialsPath, JSON.stringify({ jwt: 'sample.jwt.value', seed: 'SUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', }), 'utf8'); fs.writeFileSync( path.join(distDir, 'index.html'), 'fixture', 'utf8', ); const loadedEnvironment: ILoadedMatrixPackageEnvironment = { packageDir, envName: 'host', environmentPath: path.join(packageDir, '.matrix', 'host.environment.json'), environment: { name: 'host', runtime: { root: 'COM.TEST.EXTERNAL' }, nats: { mode: 'external', url: 'nats://example.test:4222', wsUrl: 'wss://example.test/nats-ws', credentialsRef: `file:${credentialsPath}`, }, http: { enabled: true, port: httpPort, }, }, }; const webapp: ILoadedMatrixWebappManifest = { packageDir, packageName: '@acme/webapp', manifestPath: path.join(packageDir, 'matrix.json'), distDir, entryFile: 'index.html', appName: 'webapp', }; const runnerTransport: IResolvedRunnerTransportPlan = { envName: 'host', root: 'COM.TEST.EXTERNAL', mode: 'external', url: 'nats://example.test:4222', wsUrl: 'wss://example.test/nats-ws', credentialsRef: `file:${credentialsPath}`, }; const server = await startStandaloneWebappServer({ loadedEnvironment, webapp, runnerTransport, }); try { const bootstrap = await fetch(`${server.baseUrl}/api/bootstrap`); assert.equal(bootstrap.status, 200); const bootstrapPayload = await bootstrap.json() as { authorityContext?: { assetHostRoot?: string; platformServiceRoot?: string; sessionAuthorityRoot?: string | null; selectedAuthorityRoot?: string | null; runtimeInstanceRoot?: string | null; isAuthenticated?: boolean; isPlatformAdmin?: boolean; selectableAuthorityRoots?: string[]; }; authorityRoot?: string; busRoot?: string; runtimeInstanceRoot?: string | null; transportPlan?: { authMode?: string; authEndpoint?: string | null; wsPath?: string; }; sources?: { transportAuthMode?: string; }; }; assert.deepEqual(bootstrapPayload.authorityContext, { assetHostRoot: 'COM.TEST.EXTERNAL', platformServiceRoot: 'COM.TEST.EXTERNAL', sessionAuthorityRoot: 'COM.TEST.EXTERNAL', selectedAuthorityRoot: 'COM.TEST.EXTERNAL', runtimeInstanceRoot: null, isAuthenticated: true, isPlatformAdmin: false, selectableAuthorityRoots: ['COM.TEST.EXTERNAL'], }); assert.equal(bootstrapPayload.authorityRoot, 'COM.TEST.EXTERNAL'); assert.equal(bootstrapPayload.busRoot, 'COM.TEST.EXTERNAL'); assert.equal(bootstrapPayload.runtimeInstanceRoot, null); assert.equal(bootstrapPayload.transportPlan?.wsPath, '/nats-ws'); assert.equal(bootstrapPayload.transportPlan?.authMode, 'jwt'); assert.equal(bootstrapPayload.transportPlan?.authEndpoint, '/api/nats-jwt'); assert.equal(bootstrapPayload.sources?.transportAuthMode, 'credentials-ref'); const auth = await fetch(`${server.baseUrl}/api/nats-jwt`, { method: 'POST' }); assert.equal(auth.status, 200); const authPayload = await auth.json() as { mode?: string; jwt?: string; seed?: string; }; assert.equal(authPayload.mode, 'jwt'); assert.equal(authPayload.jwt, 'sample.jwt.value'); assert.equal(authPayload.seed, 'SUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); } finally { await server.shutdown(); } }); it('forwards explicit upstream WebSocket paths without duplicating /nats-ws', async () => { const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'standalone-webapp-server-proxy-')); const packageDir = path.join(tempRoot, 'package'); const distDir = path.join(packageDir, 'dist'); fs.mkdirSync(distDir, { recursive: true }); fs.writeFileSync( path.join(distDir, 'index.html'), 'fixture', 'utf8', ); const httpPort = await getAvailablePort(); const upstreamPort = await getAvailablePort(); let capturedRequest = ''; const upstream = net.createServer(); const captured = new Promise((resolve) => { upstream.on('connection', (socket) => { socket.once('data', (chunk: Buffer) => { capturedRequest = chunk.toString('utf8'); socket.end('HTTP/1.1 404 Not Found\r\nConnection: close\r\nContent-Length: 0\r\n\r\n'); resolve(); }); }); }); await new Promise((resolve, reject) => { upstream.once('error', reject); upstream.listen(upstreamPort, '127.0.0.1', () => { upstream.off('error', reject); resolve(); }); }); const loadedEnvironment: ILoadedMatrixPackageEnvironment = { packageDir, envName: 'host', environmentPath: path.join(packageDir, '.matrix', 'host.environment.json'), environment: { name: 'host', runtime: { root: 'COM.TEST.EXTERNAL' }, nats: { mode: 'external', url: `nats://127.0.0.1:${upstreamPort}`, wsUrl: `ws://127.0.0.1:${upstreamPort}/nats-ws`, }, http: { enabled: true, port: httpPort, }, }, }; const webapp: ILoadedMatrixWebappManifest = { packageDir, packageName: '@acme/webapp', manifestPath: path.join(packageDir, 'matrix.json'), distDir, entryFile: 'index.html', appName: 'webapp', }; const runnerTransport: IResolvedRunnerTransportPlan = { envName: 'host', root: 'COM.TEST.EXTERNAL', mode: 'external', url: `nats://127.0.0.1:${upstreamPort}`, wsUrl: `ws://127.0.0.1:${upstreamPort}/nats-ws`, }; const server = await startStandaloneWebappServer({ loadedEnvironment, webapp, runnerTransport, }); const client = net.connect(httpPort, '127.0.0.1'); try { await new Promise((resolve) => { client.once('connect', resolve); }); client.write([ 'GET /nats-ws?probe=1 HTTP/1.1', `Host: 127.0.0.1:${httpPort}`, 'Connection: Upgrade', 'Upgrade: websocket', 'Origin: http://127.0.0.1:9999', 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==', 'Sec-WebSocket-Version: 13', '', '', ].join('\r\n')); await captured; assert.match(capturedRequest, /^GET \/nats-ws\?probe=1 HTTP\/1\.1\r\n/); assert.doesNotMatch(capturedRequest, /\/nats-ws\/nats-ws/); assert.doesNotMatch(capturedRequest, /\r\nOrigin:/i); } finally { client.destroy(); await server.shutdown(); await new Promise((resolve) => { upstream.close(() => resolve()); }); } }); });