/** * Live transcript, phase 1: inactive-provider + auth-gate outcomes over a * real socket. Self-authenticating: prints git HEAD and ASSERTS it matches * PINNED_ANCESTOR lineage, asserts every expected status/body, exits non-zero on any * mismatch. Booted with the REAL app (createApp); fresh boot = no active * provider. */ 'use strict'; const http = require('http'); const { execSync } = require('child_process'); const { createApp } = require('../src/app'); // Exact-head evidence: HEAD must descend from the pinned functional commit // (a commit cannot embed its own hash; the exact HEAD is printed at runtime). const PINNED_ANCESTOR = '51ba85fc69249f4db0e9cc1d17594882ca59aa57'; function req(port, method, path, headers = {}) { return new Promise((resolve, reject) => { const r = http.request({ host: '127.0.0.1', port, method, path, headers }, (res) => { let body = ''; res.on('data', (c) => { body += c; }); res.on('end', () => resolve({ status: res.statusCode, headers: res.headers, body })); }); r.on('error', reject); r.end(); }); } let FAILURES = 0; function expect(name, actual, predicate, rendered) { const ok = predicate(actual); console.log(`< assert ${name}: ${ok ? 'PASS' : 'FAIL'} (${rendered || actual})`); if (!ok) FAILURES += 1; } async function main() { const head = execSync('git -C .. rev-parse HEAD', { encoding: 'utf8' }).trim(); console.log(`# git HEAD: ${head} (must descend from ${PINNED_ANCESTOR.slice(0, 7)})`); const anc = execSync(`git -C .. merge-base --is-ancestor ${PINNED_ANCESTOR} HEAD && echo yes`, { encoding: 'utf8' }).trim(); expect('head.on-p7-lineage', anc, (a) => a === 'yes'); const { app } = await createApp(); const server = app.listen(0, '127.0.0.1'); await new Promise((r) => server.on('listening', r)); const port = server.address().port; const show = (label, method, path, headers, res) => { console.log(`### ${label}`); console.log(`> ${method} http://127.0.0.1:${port}${path}`); for (const [k, v] of Object.entries(headers)) console.log(`> ${k}: ${v}`); console.log(`< HTTP ${res.status}`); console.log(`< body: ${res.body.slice(0, 260)}`); console.log(''); }; const FA = '/api/v1/network/forward-auth/'; let res = await req(port, 'GET', FA, { 'X-Forwarded-For': '10.53.0.7' }); show('forward-auth, provider inactive (fresh boot) → 503 network provider not active', 'GET', FA, { 'X-Forwarded-For': '10.53.0.7' }, res); expect('fa-inactive-xf.status=503', res.status, (s) => s === 503); expect('fa-inactive-xf.error', res.body, (b) => b.includes('network provider not active')); res = await req(port, 'GET', FA); show('forward-auth, direct request (no headers), provider inactive → 503', 'GET', FA, {}, res); expect('fa-inactive-direct.status=503', res.status, (s) => s === 503); res = await req(port, 'POST', FA, { 'X-Forwarded-For': '10.53.0.7', 'X-Forwarded-Host': 'plex.sami' }); show('forward-auth POST parity, provider inactive → 503', 'POST', FA, { 'X-Forwarded-For': '10.53.0.7', 'X-Forwarded-Host': 'plex.sami' }, res); expect('fa-inactive-post.status=503', res.status, (s) => s === 503); res = await req(port, 'GET', '/api/v1/network/people'); show('people list, unauthenticated → auth gate 401 (route mounted, gated)', 'GET', '/api/v1/network/people', {}, res); expect('people-gate.status=401', res.status, (s) => s === 401); res = await req(port, 'GET', '/api/v1/network/wizard/state'); show('wizard state, unauthenticated → auth gate 401 (route mounted, gated)', 'GET', '/api/v1/network/wizard/state', {}, res); expect('wizard-gate.status=401', res.status, (s) => s === 401); res = await req(port, 'GET', '/api/v1/network/wg/redeem/nonexistent-token'); show('wg redeem, bogus token (public route) → 503 (route mounted, sessionless)', 'GET', '/api/v1/network/wg/redeem/nonexistent-token', {}, res); expect('wg-redeem-gate.status=503', res.status, (s) => s === 503); expect('wg-redeem-gate.error', res.body, (b) => b.includes('network provider not active')); await new Promise((r) => server.close(r)); console.log(`# asserts: ${FAILURES === 0 ? 'ALL PASS' : FAILURES + ' FAILURES'}`); process.exit(FAILURES === 0 ? 0 : 1); } main().catch((e) => { console.error('FATAL', e && e.message); process.exit(1); });