deploy
This commit is contained in:
+64
-5
@@ -2,6 +2,7 @@ import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { execFileSync, spawnSync } from 'node:child_process';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { mkdtemp, rm } from 'node:fs/promises';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
@@ -11,7 +12,7 @@ import { CHAIN_ID, GENESIS_TIME, GENESIS_HASH, MAX_TARGET } from '../server/test
|
||||
|
||||
function script(code: string, env: Record<string,string> = {}) {
|
||||
return execFileSync(process.execPath, ['--experimental-strip-types', '--input-type=module', '-e', code], {
|
||||
env: { ...process.env, WIKIDECK_NETWORK: 'mainnet', WIKIDECK_GENESIS_TIME: '1798761600', ...env }, encoding: 'utf8', timeout: 30000,
|
||||
env: { ...process.env, WIKIDECK_NETWORK: 'mainnet', WIKIDECK_GENESIS_TIME: '1793491200', ...env }, encoding: 'utf8', timeout: 30000,
|
||||
}).trim();
|
||||
}
|
||||
test('default profile is mainnet while testnet remains an explicit isolated profile', () => {
|
||||
@@ -38,14 +39,15 @@ test('mainnet candidate has distinct deterministic genesis, signatures and stric
|
||||
});
|
||||
test('mainnet startup is blocked before resources open, while manifest inspection needs no launch approval', () => {
|
||||
const args = ['--experimental-strip-types', 'server/index.ts'];
|
||||
const env = { ...process.env, WIKIDECK_NETWORK: 'mainnet', WIKIDECK_GENESIS_TIME: '1798761600', WIKIDECK_MAINNET_LAUNCH: '', WIKIDECK_MAINNET_RISK_ACK: '' };
|
||||
const env = { ...process.env, WIKIDECK_NETWORK: 'mainnet', WIKIDECK_GENESIS_TIME: '1793491200', WIKIDECK_MAINNET_LAUNCH: '', WIKIDECK_MAINNET_RISK_ACK: '' };
|
||||
const result = spawnSync(process.execPath, args, { env, encoding: 'utf8', timeout: 30000 });
|
||||
assert.notEqual(result.status, 0); assert.match(result.stderr, /launch-gated/);
|
||||
const manifest = JSON.parse(execFileSync(process.execPath, [...args, '--network-manifest'], { env, encoding: 'utf8' }));
|
||||
assert.equal(manifest.profile, 'mainnet'); assert.equal(manifest.audited, false);
|
||||
assert.equal(manifest.launchStatus, 'candidate-gated');
|
||||
assert.equal(manifest.privatePeersSupported, true);
|
||||
});
|
||||
test('mainnet gates require genesis time, chain-specific approval, HTTPS, and independent peers', () => {
|
||||
test('mainnet gates require genesis time, chain-specific approval, HTTPS browser origin, and distinct peers', () => {
|
||||
const result = JSON.parse(script(`
|
||||
import { assertLaunchAllowed } from './server/launch.ts';
|
||||
import { CHAIN_ID, GENESIS_TIME } from './server/testnet/consensus.ts';
|
||||
@@ -61,7 +63,64 @@ test('mainnet gates require genesis time, chain-specific approval, HTTPS, and in
|
||||
}
|
||||
console.log(JSON.stringify(results));
|
||||
`));
|
||||
assert.deepEqual(result, [false,false,false,false,false,false,false,true]);
|
||||
assert.deepEqual(result, [false,false,false,false,false,false,true,true]);
|
||||
});
|
||||
test('private mainnet cluster peers require explicit opt-in and preserve every other launch gate', () => {
|
||||
const result = JSON.parse(script(`
|
||||
import { assertLaunchAllowed } from './server/launch.ts';
|
||||
import { CHAIN_ID, GENESIS_TIME } from './server/testnet/consensus.ts';
|
||||
const env={WIKIDECK_MAINNET_LAUNCH:CHAIN_ID,WIKIDECK_MAINNET_RISK_ACK:'operator-accepts-unaudited-risk',
|
||||
PUBLIC_ORIGIN:'https://wikideck.example',WIKIDECK_ALLOW_PRIVATE_PEERS:'1',
|
||||
WIKIDECK_PEERS:'http://wikideck-peer-a.wikideck.svc.cluster.local:80,http://wikideck-peer-b.wikideck.svc.cluster.local:80'};
|
||||
const cases=[[{},GENESIS_TIME*1000], [{},GENESIS_TIME*1000-1],
|
||||
[{WIKIDECK_ALLOW_PRIVATE_PEERS:'0'},Infinity], [{WIKIDECK_ALLOW_PRIVATE_PEERS:'true'},Infinity],
|
||||
[{WIKIDECK_MAINNET_LAUNCH:'wrong'},Infinity], [{WIKIDECK_MAINNET_RISK_ACK:''},Infinity],
|
||||
[{PUBLIC_ORIGIN:'http://wikideck.example'},Infinity], [{WIKIDECK_PEERS:''},Infinity],
|
||||
[{WIKIDECK_PEERS:'http://peer-a:80,http://peer-a/'},Infinity],
|
||||
[{WIKIDECK_PEERS:'http://peer-a,http://user:password@peer-b'},Infinity],
|
||||
[{WIKIDECK_PEERS:'http://peer-a,http://peer-b/p2p'},Infinity],
|
||||
[{WIKIDECK_PEERS:'http://peer-a,http://peer-b?x=1'},Infinity],
|
||||
[{WIKIDECK_PEERS:'http://peer-a,https://wikideck.example'},Infinity],
|
||||
[{WIKIDECK_PEERS:'http://peer-a,ftp://peer-b'},Infinity]];
|
||||
console.log(JSON.stringify(cases.map(([changes,now])=>{
|
||||
try {assertLaunchAllowed({...env,...changes},now);return true;}catch{return false;}
|
||||
})));
|
||||
`));
|
||||
assert.deepEqual(result, [true, ...Array(13).fill(false)]);
|
||||
});
|
||||
test('default mainnet genesis can launch on November 1 and matches browser, Docker and Compose identities', () => {
|
||||
const result = JSON.parse(script(`
|
||||
delete process.env.WIKIDECK_GENESIS_TIME;
|
||||
delete process.env.WIKIDECK_IMAGE_NETWORK;
|
||||
delete process.env.WIKIDECK_IMAGE_GENESIS_TIME;
|
||||
const { assertLaunchAllowed, launchManifest } = await import('./server/launch.ts');
|
||||
const { expectedChainIdentity } = await import('./shared/chain-identity.ts');
|
||||
const manifest = launchManifest();
|
||||
assertLaunchAllowed({WIKIDECK_MAINNET_LAUNCH:manifest.chainId,
|
||||
WIKIDECK_MAINNET_RISK_ACK:'operator-accepts-unaudited-risk',PUBLIC_ORIGIN:'https://wikideck.eom.dev',
|
||||
WIKIDECK_ALLOW_PRIVATE_PEERS:'1',
|
||||
WIKIDECK_PEERS:'http://wikideck-peer-a.wikideck.svc.cluster.local:80,http://wikideck-peer-b.wikideck.svc.cluster.local:80'},
|
||||
Date.UTC(2026,10,1));
|
||||
console.log(JSON.stringify({manifest,identity:await expectedChainIdentity()}));
|
||||
`));
|
||||
assert.equal(result.manifest.genesisTime, 1_793_491_200);
|
||||
assert.equal(result.manifest.chainId, result.identity.chainId);
|
||||
assert.equal(result.manifest.genesis, result.identity.genesis);
|
||||
const dockerfile = readFileSync(new URL('../Dockerfile', import.meta.url), 'utf8');
|
||||
assert.equal(dockerfile.match(/^ARG WIKIDECK_GENESIS_TIME=1793491200\r?$/gm)?.length, 2);
|
||||
for (const name of ['compose.yaml', 'compose.mainnet.yaml']) {
|
||||
const compose = readFileSync(new URL('../' + name, import.meta.url), 'utf8');
|
||||
assert.equal(compose.match(/WIKIDECK_GENESIS_TIME:-1793491200/g)?.length, 2);
|
||||
}
|
||||
});
|
||||
test('runtime cannot silently change the image-baked mainnet genesis', () => {
|
||||
const result = spawnSync(process.execPath, ['--experimental-strip-types', 'server/index.ts', '--network-manifest'], {
|
||||
env: { ...process.env, WIKIDECK_NETWORK: 'mainnet', WIKIDECK_GENESIS_TIME: '1793491200',
|
||||
WIKIDECK_IMAGE_NETWORK: 'mainnet', WIKIDECK_IMAGE_GENESIS_TIME: '1798761600' },
|
||||
encoding: 'utf8', timeout: 30000,
|
||||
});
|
||||
assert.notEqual(result.status, 0);
|
||||
assert.match(result.stderr, /Runtime genesis time does not match/);
|
||||
});
|
||||
test('mainnet ledger uses its isolated folder; testnet backup headers are rejected', async () => {
|
||||
const dir = await mkdtemp(join(tmpdir(), 'wikideck-network-'));
|
||||
@@ -91,7 +150,7 @@ test('operator preflight is read-only, fails closed, and does not disclose crede
|
||||
const dataDir = join(dir, 'must-not-be-created');
|
||||
const secret = 'test-only-sensitive-value-must-not-appear';
|
||||
const result = spawnSync(process.execPath, ['--experimental-strip-types', 'server/index.ts', '--launch-preflight'], {
|
||||
env: { ...process.env, WIKIDECK_NETWORK: 'mainnet', WIKIDECK_GENESIS_TIME: '1798761600', WIKIDECK_DATA_DIR: dataDir,
|
||||
env: { ...process.env, WIKIDECK_NETWORK: 'mainnet', WIKIDECK_GENESIS_TIME: '1793491200', WIKIDECK_DATA_DIR: dataDir,
|
||||
WIKIDECK_MAINNET_LAUNCH: '', WIKIDECK_MAINNET_RISK_ACK: '', PAYMENT_PROVIDER_API_KEY: secret },
|
||||
encoding: 'utf8', timeout: 30000,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user