Files
Hermes 75a0385c38
CI / Test & Lint (pull_request) Canceled after 0s
CI / Security audit (pull_request) Canceled after 0s
P7 r10: probes assert expected head + every outcome (nonzero exit on mismatch); phase-2 rejection-path cleanup guaranteed
2026-10-04 00:07:56 -07:00

91 lines
4.2 KiB
JavaScript

/**
* 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); });