// Test-only reverse proxy around the unmodified pinned upstream application. import fs from 'node:fs'; import http from 'node:http'; import https from 'node:https'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; import { randomBytes } from 'node:crypto'; import { once } from 'node:events'; import { startIdentityProvider } from './oidc-fixture.mjs'; const [upstream, directory] = process.argv.slice(2); process.env.PORT = '0'; process.env.BIND_ADDRESS = '127.0.0.1'; process.env.DB_PATH = path.join(directory, 'fixture.db'); process.env.SESSION_SECRET = randomBytes(48).toString('hex'); // Exercise both explicit Secure cookies and upstream's default behind HTTPS. const sessionSecure = process.env.YUVOMI_TEST_SESSION_SECURE ?? 'true'; if (!['true', 'false'].includes(sessionSecure)) throw new Error('Invalid fixture cookie mode'); process.env.SESSION_SECURE = sessionSecure; process.env.DB_ENCRYPTION_KEY = ''; process.env.NODE_ENV = 'test'; process.env.LOG_LEVEL = 'warn'; const tls = { key: fs.readFileSync(path.join(directory, 'key.pem')), cert: fs.readFileSync(path.join(directory, 'cert.pem')) }; const idp = await startIdentityProvider(tls); process.env.OIDC_ISSUER = idp.issuer; process.env.OIDC_CLIENT_ID = idp.clientId; process.env.OIDC_CLIENT_SECRET = idp.secret; const { server } = await import(pathToFileURL(path.join(upstream, 'server/index.js'))); if (!server.listening) await once(server, 'listening'); let networkAvailable = true; const proxy = https.createServer(tls, (request, response) => { // Fault injection lives only in this loopback fixture, never in upstream/app code. if (request.method === 'POST' && ['/__mobile_test/network/off', '/__mobile_test/network/on'].includes(request.url)) { networkAvailable = request.url.endsWith('/on'); response.writeHead(200, { 'Content-Type': 'application/json' }); response.end('{}'); return; } if (!networkAvailable) { request.socket.destroy(); return; } const backend = http.request({ hostname: '127.0.0.1', port: server.address().port, method: request.method, path: request.url, headers: { ...request.headers, 'x-forwarded-proto': 'https', 'x-forwarded-for': '127.0.0.1' }, }, incoming => { response.writeHead(incoming.statusCode, incoming.headers); incoming.pipe(response); }); backend.on('error', () => { response.writeHead(502); response.end(); }); request.pipe(backend); }); proxy.listen(0, '127.0.0.1'); await once(proxy, 'listening'); process.env.OIDC_REDIRECT_URI = `https://127.0.0.1:${proxy.address().port}/api/v1/auth/oidc/callback`; idp.setRedirect(process.env.OIDC_REDIRECT_URI); fs.writeFileSync(path.join(directory, 'ready.json'), JSON.stringify({ port: proxy.address().port, idpPort: idp.port })); process.on('SIGTERM', () => { idp.close(); proxy.close(); server.close(); process.exit(0); });