56 lines
4.2 KiB
TypeScript
Executable File
56 lines
4.2 KiB
TypeScript
Executable File
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { trustedProxies, operationsPort, startOperations } from '../server/operations.ts';
|
|
import express from 'express';
|
|
import { once } from 'node:events';
|
|
import { createServer } from 'node:net';
|
|
import { checkOperations } from '../server/operations-check.ts';
|
|
|
|
test('proxy trust is explicit literal IP/CIDR only; defaults disabled',()=>{
|
|
assert.deepEqual(trustedProxies({}),[]);
|
|
assert.deepEqual(trustedProxies({WIKIDECK_TRUSTED_PROXIES:'127.0.0.1,::1,172.20.1.0/24'}),['127.0.0.1','::1','172.20.1.0/24']);
|
|
for(const value of ['true','1','loopback','localhost','0.0.0.0/0','::/0','127.0.0.1/33','127.0.0.1,','http://proxy'])assert.throws(()=>trustedProxies({WIKIDECK_TRUSTED_PROXIES:value}));
|
|
assert.equal(operationsPort({}),undefined);
|
|
for(const value of ['0','-1','65536','x'])assert.throws(()=>operationsPort({WIKIDECK_OPS_PORT:value}));
|
|
});
|
|
test('untrusted forwarded headers do not alter client IP; explicit loopback proxy is recognized',async t=>{
|
|
const app=express();app.get('/ip',(req,res)=>{res.json({ip:req.ip});});
|
|
const server=app.listen(0,'127.0.0.1');await once(server,'listening');
|
|
t.after(()=>{server.closeAllConnections();server.close();});
|
|
const a=server.address();assert.ok(a&&typeof a==='object');const url=`http://127.0.0.1:${a.port}/ip`;
|
|
const request=()=>fetch(url,{headers:{'X-Forwarded-For':'203.0.113.12'}}).then(r=>r.json());
|
|
assert.equal((await request()).ip,'127.0.0.1');
|
|
app.set('trust proxy',trustedProxies({WIKIDECK_TRUSTED_PROXIES:'127.0.0.1'}));
|
|
assert.equal((await request()).ip,'203.0.113.12');
|
|
});
|
|
test('private operations listener exposes bounded aggregates only on separate loopback port',async t=>{
|
|
const reserve=createServer();reserve.listen(0,'127.0.0.1');await once(reserve,'listening');
|
|
const a=reserve.address();assert.ok(a&&typeof a==='object');await new Promise<void>(resolve=>reserve.close(()=>resolve()));
|
|
const ops=startOperations(a.port,()=>({network:'test',native:{available:true}}));t.after(()=>ops.close());
|
|
const r=await fetch(`http://127.0.0.1:${a.port}/status`,{signal:AbortSignal.timeout(5000)});
|
|
assert.equal(r.status,200);assert.equal(r.headers.get('cache-control'),'no-store');
|
|
const data=await r.json();assert.equal(data.network,'test');assert.equal(data.native.available,true);
|
|
assert.ok(data.nodeRssBytes>0);assert.equal('privateKey' in data,false);
|
|
assert.equal((await fetch(`http://127.0.0.1:${a.port}/metrics`)).status,404);
|
|
assert.equal(ops.address?.()?.address,'127.0.0.1');
|
|
});
|
|
test('operations checks identify isolation, stale reconciliation, disk pressure and market reviews',()=>{
|
|
const now=Date.now();
|
|
const status={schema:'wikideck-operations-v1',observedAt:new Date(now).toISOString(),
|
|
native:{available:true,queued:0},ledger:{height:10,mutationQueue:0,tipAgeSeconds:60},
|
|
peers:{configured:2,connected:2},eventLoop:{meanMs:20},disk:{availableBytes:1024**3},diskSampledAt:now,
|
|
market:{queued:0,lastReconciledAt:now,orderStates:[] as {status:string;count:number}[]}};
|
|
assert.equal(checkOperations(status,now).healthy,true);
|
|
const bad={...status,native:{available:false,queued:50},peers:{configured:2,connected:0},disk:null,
|
|
market:{queued:0,lastReconciledAt:now-120000,orderStates:[{status:'review',count:1}]}};
|
|
const report=checkOperations(bad,now);
|
|
for(const warning of ['native-engine-unavailable','queue-pressure','peer-isolation','market-reconciliation-stale','market-operator-review','disk-sample-unavailable-or-stale'])assert.ok(report.warnings.includes(warning));
|
|
assert.throws(()=>checkOperations({}));
|
|
const custody = {backend:'postgres',mutationHold:false,integrityHold:false,
|
|
audit:{status:'ok',lastAttemptAt:now,lastSuccessAt:now,failureCode:null,stale:false}};
|
|
assert.equal(checkOperations({...status,custody},now).healthy,true);
|
|
const held=checkOperations({...status,custody:{...custody,mutationHold:true,integrityHold:true,
|
|
audit:{...custody.audit,status:'failed',failureCode:'order-reservation-mismatch',lastSuccessAt:now-180000,stale:true}}},now);
|
|
assert.ok(held.warnings.includes('custody-financial-review'));assert.ok(held.warnings.includes('custody-audit-stale'));
|
|
});
|