import { EventEmitter } from 'node:events'; import { lstat, mkdtemp, mkdir, rm, symlink, writeFile } from 'node:fs/promises'; import { createServer } from 'node:http'; import { tmpdir } from 'node:os'; import { join, resolve } from 'node:path'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { createRuntimeConfig, GATEWAY_AUTH_HEADER } from './runtime-config.js'; import { buildApp } from './app.js'; import { createCanaryGateway, type CanaryGateway } from './canary-gateway.js'; import { createProductionReadiness } from './production-readiness.js'; import { defaultKeychainMetadataCheck } from './production-readiness.js'; import { readCanaryRuntimeOptions } from './canary-runtime.js'; import { installBoundedShutdown } from './shutdown.js'; import { secureTokenEqual } from './app.js'; import { openDatabase } from './infrastructure/database/database.js'; import { migrateDatabase } from './infrastructure/database/migrations.js'; const cleanup: Array<() => Promise> = []; afterEach(async () => { await Promise.all(cleanup.splice(0).map((fn) => fn())); }); const token = 'runtime-gateway-token-with-at-least-32-bytes'; describe('production runtime foundation', () => { it('creates one deeply immutable fixed-listener config and validates before side effects', () => { const root = resolve('/tmp/multi-simadmin-data'); const config = createRuntimeConfig({ MULTI_SIMADMIN_DATA_ROOT: root, MULTI_SIMADMIN_DATABASE_PATH: join(root, 'db.sqlite'), MULTI_SIMADMIN_GATEWAY_TOKEN: token, MULTI_SIMADMIN_WEB_DIST: root, API_HOST: '127.0.0.1', API_PORT: '8790', }); expect(config).toEqual({ api: { host: '127.0.0.1', port: 8790 }, dataRoot: root, databasePath: join(root, 'db.sqlite'), gatewayToken: token, webDist: root, }); expect(Object.isFrozen(config)).toBe(true); expect(Object.isFrozen(config.api)).toBe(true); expect(() => createRuntimeConfig({ MULTI_SIMADMIN_DATA_ROOT: root, MULTI_SIMADMIN_DATABASE_PATH: '/tmp/escape.sqlite', MULTI_SIMADMIN_GATEWAY_TOKEN: token, MULTI_SIMADMIN_WEB_DIST: root, }), ).toThrow(/data root/i); expect(() => createRuntimeConfig({ MULTI_SIMADMIN_DATA_ROOT: root, MULTI_SIMADMIN_DATABASE_PATH: join(root, 'db.sqlite'), MULTI_SIMADMIN_GATEWAY_TOKEN: 'weak', }), ).toThrow(/token/i); }); it('rejects a database path whose existing symlink ancestor escapes before creating a DB', async () => { const directory = await mkdtemp(join(tmpdir(), 'runtime-containment-')); cleanup.push(() => rm(directory, { recursive: true, force: true })); const root = join(directory, 'data'); const outside = join(directory, 'outside'); await mkdir(root); await mkdir(outside); await symlink(outside, join(root, 'escape')); const databasePath = join(root, 'escape', 'db.sqlite'); expect(() => createRuntimeConfig({ MULTI_SIMADMIN_DATA_ROOT: root, MULTI_SIMADMIN_DATABASE_PATH: databasePath, MULTI_SIMADMIN_GATEWAY_TOKEN: token, MULTI_SIMADMIN_WEB_DIST: root, }), ).toThrow(/data root|symlink/i); await expect(lstat(join(outside, 'db.sqlite'))).rejects.toMatchObject({ code: 'ENOENT' }); }); it('reads and validates the canary gateway token from its environment', () => { expect( readCanaryRuntimeOptions({ MULTI_SIMADMIN_GATEWAY_TOKEN: token, CANARY_DIST_DIR: '/tmp/dist', CANARY_PORT: '8789', CANARY_UPSTREAM_PORT: '8790', }), ).toMatchObject({ gatewayToken: token, port: 8789, upstreamPort: 8790, }); expect(() => readCanaryRuntimeOptions({ CANARY_DIST_DIR: '/tmp/dist' })).toThrow(/token/i); expect(() => readCanaryRuntimeOptions({ CANARY_DIST_DIR: '/tmp/dist', MULTI_SIMADMIN_GATEWAY_TOKEN: 'weak', }), ).toThrow(/token/i); }); it('always compares fixed-size token digests with timingSafeEqual', () => { const compare = vi.fn(() => false); expect(secureTokenEqual('x', token, compare)).toBe(false); expect(compare).toHaveBeenCalledOnce(); const [actual, expected] = compare.mock.calls[0] as unknown as [Buffer, Buffer]; expect(actual).toHaveLength(32); expect(expected).toHaveLength(32); }); it('forces pluggable termination when graceful shutdown exceeds its deadline', async () => { vi.useFakeTimers(); const target = new EventEmitter(); const terminate = vi.fn(); const stop = installBoundedShutdown( target, { close: () => new Promise(() => undefined) }, { timeoutMs: 25, terminate }, ); const stopping = stop(); await vi.advanceTimersByTimeAsync(25); await stopping; expect(terminate).toHaveBeenCalledOnce(); vi.useRealTimers(); }); it('default Keychain readiness checks only Darwin security executable metadata', async () => { const stat = vi.fn(async () => ({ isFile: () => true, mode: 0o100755 })); await expect(defaultKeychainMetadataCheck('darwin', stat)).resolves.toBe(true); expect(stat).toHaveBeenCalledExactlyOnceWith('/usr/bin/security'); stat.mockClear(); await expect(defaultKeychainMetadataCheck('linux', stat)).resolves.toBe(false); expect(stat).not.toHaveBeenCalled(); }); it('authenticates internal requests without reflecting credentials', async () => { const app = buildApp({ gatewayToken: token }); cleanup.push(() => app.close()); expect((await app.inject({ url: '/healthz' })).statusCode).toBe(401); expect( ( await app.inject({ url: '/healthz', headers: { [GATEWAY_AUTH_HEADER]: 'wrong-but-same-length-xxxxxxxxxxxxxxxxx' }, }) ).statusCode, ).toBe(401); const ok = await app.inject({ url: '/healthz', headers: { [GATEWAY_AUTH_HEADER]: token } }); expect(ok.statusCode).toBe(200); expect(ok.payload).not.toContain(token); }); it('readiness checks a live migrated DB and auth configuration without reading secrets', async () => { const directory = await mkdtemp(join(tmpdir(), 'runtime-ready-')); cleanup.push(() => rm(directory, { recursive: true, force: true })); const db = openDatabase(join(directory, 'db.sqlite')); migrateDatabase(db); const keychainMetadataCheck = vi.fn(async () => true); const readiness = createProductionReadiness({ db, gatewayToken: token, keychainMetadataCheck, assetsCheck: async () => true, recoveryMarkersCheck: async () => 0, upstreamGatewayCheck: async () => true, }); expect(await readiness()).toEqual({ ready: true, checks: { database: 'ready', migrations: 'ready', gatewayAuth: 'ready', keychain: 'ready', pendingCredentials: 'ready', assets: 'ready', recoveryMarkers: 'ready', upstreamGateway: 'ready', }, }); expect(keychainMetadataCheck).toHaveBeenCalledOnce(); db.close(); expect((await readiness()).ready).toBe(false); }); it('gateway replaces forged auth and only falls back for extensionless routes', async () => { const directory = await mkdtemp(join(tmpdir(), 'runtime-gateway-')); await mkdir(join(directory, 'assets')); await writeFile(join(directory, 'index.html'), '
SPA
'); cleanup.push(() => rm(directory, { recursive: true, force: true })); let seen: string | string[] | undefined; const upstream = createServer((request, response) => { seen = request.headers[GATEWAY_AUTH_HEADER]; response.end('ok'); }); await new Promise((done) => upstream.listen(0, '127.0.0.1', done)); cleanup.push(() => new Promise((done) => upstream.close(() => done()))); const address = upstream.address(); if (!address || typeof address === 'string') throw new Error('address'); const gateway: CanaryGateway = createCanaryGateway({ distDir: directory, port: 0, upstreamPort: address.port, gatewayToken: token, }); await gateway.start(); cleanup.push(() => gateway.stop()); await fetch(`${gateway.origin}/healthz`, { headers: { [GATEWAY_AUTH_HEADER]: 'forged' } }); expect(seen).toBe(token); expect((await fetch(`${gateway.origin}/assets/missing.js`)).status).toBe(404); expect((await fetch(`${gateway.origin}/missing.css`)).status).toBe(404); expect((await fetch(`${gateway.origin}/instances/one`)).status).toBe(200); }); });