import test from 'node:test'; import assert from 'node:assert/strict'; import { execFileSync, spawnSync } from 'node:child_process'; import { chmod, mkdtemp, rm, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import { loadPilotMoneroDepositRequestFile } from '../server/market/pilot-monero-deposit-request-file.ts'; function run(code: string) { return JSON.parse(execFileSync(process.execPath, ['--experimental-strip-types', '--input-type=module', '-e', code], { env: { ...process.env, WIKIDECK_NETWORK: 'pilot' }, encoding: 'utf8', timeout: 30_000, }).trim()); } const requestFixture = ` import { generateKeyPairSync, sign } from 'node:crypto'; import { address } from './server/testnet/consensus.ts'; import { CHAIN_ID } from './server/testnet/consensus.ts'; import { pilotMoneroDepositRequestMessage } from './shared/pilot-monero-deposit.ts'; import { validatePilotMoneroDepositRequest } from './server/market/pilot-monero-deposit-request.ts'; const pair=generateKeyPairSync('ec',{namedCurve:'prime256v1'}); const publicKey=pair.publicKey.export({type:'spki',format:'der'}).toString('base64'); const beneficiary=address(publicKey), now=1_800_000_000_000; const identity={version:1,mode:'pilot-custody',policy:'pilot-custody-v1',marketNetwork:'wikideck-randomx-pilot-1', marketChainId:CHAIN_ID,moneroNetwork:'mainnet',custodianId:'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa', activationStatus:'identity-only',initializedAt:now-1}; const context={identity,walletGenerationId:'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb', walletFingerprint:'c'.repeat(64),accountIndex:2,now:()=>now}; const unsigned={version:1,marketNetwork:'wikideck-randomx-pilot-1',marketChainId:CHAIN_ID,moneroNetwork:'mainnet', custodianId:identity.custodianId,beneficiary,publicKey,requestId:'dddddddd-dddd-4ddd-8ddd-dddddddddddd', walletGenerationId:context.walletGenerationId,walletFingerprint:context.walletFingerprint,accountIndex:2,expiresAt:now+60_000}; const signature=sign('sha256',Buffer.from(pilotMoneroDepositRequestMessage(unsigned)), {key:pair.privateKey,dsaEncoding:'ieee-p1363'}).toString('base64'); const request={...unsigned,signature}; `; test('pilot deposit authorization binds both networks and validates without allocating an address', () => { const result = run(`${requestFixture} const intent=validatePilotMoneroDepositRequest(context,request); console.log(JSON.stringify({intent,hasAddress:Object.hasOwn(intent,'address'),hasAddressIndex:Object.hasOwn(intent,'addressIndex')}));`); assert.equal(result.intent.marketNetwork, 'wikideck-randomx-pilot-1'); assert.match(result.intent.marketChainId, /^[a-f0-9]{64}$/); assert.equal(result.intent.moneroNetwork, 'mainnet'); assert.equal(result.intent.beneficiary.length, 64); assert.match(result.intent.requestDigest, /^[a-f0-9]{64}$/); assert.equal(result.hasAddress, false); assert.equal(result.hasAddressIndex, false); }); test('pilot deposit authorization rejects domain, identity, wallet, signer, signature, and expiry mismatches', () => { const result = run(`${requestFixture} const rejected=[]; const check=(label,ctx,raw)=>{try{validatePilotMoneroDepositRequest(ctx,raw);rejected.push([label,false]);} catch{rejected.push([label,true]);}}; check('market-network',context,{...request,marketNetwork:'wikideck-randomx-mainnet-1'}); check('monero-network',context,{...request,moneroNetwork:'stagenet'}); check('chain-id',context,{...request,marketChainId:'e'.repeat(64)}); check('custodian',context,{...request,custodianId:'eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee'}); check('wallet-generation',{...context,walletGenerationId:'ffffffff-ffff-4fff-8fff-ffffffffffff'},request); check('wallet-fingerprint',{...context,walletFingerprint:'d'.repeat(64)},request); check('account-index',{...context,accountIndex:3},request); check('signer',context,{...request,beneficiary:'1'.repeat(64)}); check('signature',context,{...request,signature:'A'.repeat(88)}); check('expired',{...context,now:()=>request.expiresAt+1},request); check('too-far-future',{...context,now:()=>request.expiresAt+1},{...request,expiresAt:request.expiresAt+10*60_000}); check('not-identity-only',{...context,identity:{...context.identity,activationStatus:'active'}},request); console.log(JSON.stringify(rejected));`); assert.deepEqual(result, [['market-network',true],['monero-network',true],['chain-id',true],['custodian',true], ['wallet-generation',true],['wallet-fingerprint',true],['account-index',true],['signer',true],['signature',true], ['expired',true],['too-far-future',true],['not-identity-only',true]]); }); test('pilot deposit authorization rejects malformed and unknown fields', () => { const result = run(`${requestFixture} let malformed=false,unknown=false; try{validatePilotMoneroDepositRequest(context,{...request,accountIndex:-1});}catch{malformed=true;} try{validatePilotMoneroDepositRequest(context,{...request,address:'4'.repeat(95)});}catch{unknown=true;} console.log(JSON.stringify({malformed,unknown}));`); assert.deepEqual(result, { malformed: true, unknown: true }); }); test('operator address CLI requires explicit consent before reading wallet or database configuration', () => { const result = spawnSync(process.execPath, ['--experimental-strip-types', 'scripts/pilot-monero-deposit-address.ts', '/missing/request.json'], { cwd: process.cwd(), encoding: 'utf8', timeout: 30_000, env: { ...process.env, WIKIDECK_NETWORK: 'pilot', WIKIDECK_PILOT_MODE: 'private-mock-only', WIKIDECK_PILOT_CUSTODY_OPERATIONS: '' }, }); assert.notEqual(result.status, 0); assert.match(result.stderr, /operator-triggered-addresses-only/); assert.doesNotMatch(result.stderr, /database configuration|Wallet-RPC config/); }); test('signed pilot request files must be absolute, bounded, owner-only regular files', async t => { if (process.platform === 'win32') { await assert.rejects(loadPilotMoneroDepositRequestFile('C:\\private\\request.json'), /POSIX protected-file/); return; } const directory = await mkdtemp(join(tmpdir(), 'wikideck-pilot-address-request-')); t.after(() => rm(directory, { recursive: true, force: true })); const path = join(directory, 'request.json'); await writeFile(path, JSON.stringify({ version: 1, signature: 'signed-fixture' }), { mode: 0o600 }); await chmod(path, 0o600); assert.deepEqual(await loadPilotMoneroDepositRequestFile(path), { version: 1, signature: 'signed-fixture' }); await chmod(path, 0o644); await assert.rejects(loadPilotMoneroDepositRequestFile(path), /owner-only/); await assert.rejects(loadPilotMoneroDepositRequestFile('relative.json'), /absolute/); });