Separate identity-only pilot custody foundation
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { assertCustodyDbActionAllowedOnNetwork, assertMainnetSchemaMigrationAcknowledged,
|
||||
assertMainnetCustodyOperationAcknowledged, parseCustodyDbArguments } from '../server/market/custody-db-args.ts';
|
||||
assertMainnetCustodyOperationAcknowledged, assertPilotCustodyActionAllowed,
|
||||
assertPilotSchemaMigrationAcknowledged, assertPilotCustodyIdentityAcknowledged,
|
||||
parseCustodyDbArguments } from '../server/market/custody-db-args.ts';
|
||||
|
||||
test('custody database CLI parses two-argument deposit operations without shifting arguments', () => {
|
||||
assert.deepEqual(parseCustodyDbArguments(['deposit-prepare-credit', 'a'.repeat(64), `${'b'.repeat(64)}:${'c'.repeat(64)}`]), {
|
||||
@@ -19,6 +21,9 @@ test('custody database CLI parses two-argument deposit operations without shifti
|
||||
assert.deepEqual(parseCustodyDbArguments(['grant-monero-withdrawal-runtime', 'monero_withdrawal']), {
|
||||
action: 'grant-monero-withdrawal-runtime', argument: 'monero_withdrawal', extraArgument: undefined,
|
||||
});
|
||||
assert.deepEqual(parseCustodyDbArguments(['initialize-pilot-custody-identity', 'AAAAAAAA-AAAA-4AAA-8AAA-AAAAAAAAAAAA']), {
|
||||
action: 'initialize-pilot-custody-identity', argument: 'AAAAAAAA-AAAA-4AAA-8AAA-AAAAAAAAAAAA', extraArgument: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
test('mainnet custody CLI permits only scoped Monero infrastructure grants and schema migration', () => {
|
||||
@@ -53,6 +58,22 @@ test('mainnet reviewed deposit operations require exact credit-only acknowledgem
|
||||
assert.doesNotThrow(() => assertMainnetCustodyOperationAcknowledged('grant-monero-withdrawal-runtime', undefined));
|
||||
});
|
||||
|
||||
test('pilot custody CLI permits only additive schema migration and identity-only initialization', () => {
|
||||
assert.doesNotThrow(() => assertPilotCustodyActionAllowed('migrate-pilot-schema', true));
|
||||
assert.doesNotThrow(() => assertPilotCustodyActionAllowed('initialize-pilot-custody-identity', true));
|
||||
assert.throws(() => assertPilotCustodyActionAllowed('grant-monero-observer-runtime', true), /only pilot schema migration/);
|
||||
assert.throws(() => assertPilotCustodyActionAllowed('deposit-stage-credit', true), /only pilot schema migration/);
|
||||
assert.throws(() => assertPilotCustodyActionAllowed('initialize-pilot-custody-identity', false), /requires the pilot profile/);
|
||||
assert.throws(() => assertPilotSchemaMigrationAcknowledged('migrate-pilot-schema', undefined), /acknowledgement/);
|
||||
assert.throws(() => assertPilotSchemaMigrationAcknowledged('migrate-pilot-schema', 'yes'), /acknowledgement/);
|
||||
assert.doesNotThrow(() => assertPilotSchemaMigrationAcknowledged('migrate-pilot-schema', 'explicit-pilot-schema-migration-only'));
|
||||
assert.throws(() => assertPilotCustodyIdentityAcknowledged('initialize-pilot-custody-identity', undefined, undefined), /no-funds acknowledgements/);
|
||||
assert.throws(() => assertPilotCustodyIdentityAcknowledged('initialize-pilot-custody-identity',
|
||||
'initialize-pilot-custody-v1', 'reviewed-credit-only'), /no-funds acknowledgements/);
|
||||
assert.doesNotThrow(() => assertPilotCustodyIdentityAcknowledged('initialize-pilot-custody-identity',
|
||||
'initialize-pilot-custody-v1', 'identity-only-no-funds'));
|
||||
});
|
||||
|
||||
test('custody database CLI rejects unknown, missing, empty, and excess arguments', () => {
|
||||
for (const args of [[], ['unknown'], ['audit', 'extra'], ['deposit-prepare-credit', 'wallet'],
|
||||
['deposit-prepare-credit', 'wallet', 'observation', 'extra'], ['deposit-release', '']]) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import { migrateCustody, grantCustodyRuntime, grantMoneroObserverRuntime, CUSTOD
|
||||
grantMoneroDepositCreditRuntime, grantMoneroDepositAllocatorRuntime, grantMoneroWithdrawalRuntime, CUSTODY_MIGRATION_V2,
|
||||
CUSTODY_SCHEMA_V2_DIGEST } from '../../server/market/postgres-schema.ts';
|
||||
import { parseMainnetCustodianId } from '../../server/market/mainnet-custody-identity.ts';
|
||||
import { initializePilotCustodyIdentity, parsePilotCustodianId } from '../../server/market/pilot-custody-identity.ts';
|
||||
import { readMainnetCustodyBalance, reserveMainnetWithdrawal, cancelMainnetWithdrawal } from '../../server/market/mainnet-withdrawal.ts';
|
||||
import { mainnetCustodyBalanceMessage, mainnetWithdrawalCancellationMessage, mainnetWithdrawalMessage,
|
||||
type MainnetCustodyBalanceRequestUnsigned, type MainnetWithdrawalRequestUnsigned,
|
||||
@@ -205,7 +206,7 @@ test('explicit PostgreSQL migrations are idempotent and runtime role cannot alte
|
||||
assert.equal((await f.market.audit()).assetsAtomicXmr, '1000000000000');
|
||||
});
|
||||
|
||||
test('custody schema v1 upgrades additively through v9 without dropping existing metadata', async t => {
|
||||
test('custody schema v1 upgrades additively through v10 without dropping existing metadata', async t => {
|
||||
const admin = new Pool(config);
|
||||
await admin.query('DROP SCHEMA IF EXISTS wk_custody CASCADE');
|
||||
const client = await admin.connect();
|
||||
@@ -219,13 +220,14 @@ test('custody schema v1 upgrades additively through v9 without dropping existing
|
||||
try {
|
||||
await migrateCustody(admin); await migrateCustody(admin);
|
||||
const versions = await admin.query('SELECT version FROM wk_custody.schema_versions ORDER BY version');
|
||||
assert.deepEqual(versions.rows.map(row => Number(row.version)), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
assert.deepEqual(versions.rows.map(row => Number(row.version)), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
assert.equal((await admin.query("SELECT value FROM wk_custody.custody_meta WHERE key='v1-preserved-marker'")).rows[0].value,
|
||||
'existing-test-data');
|
||||
for (const table of ['monero_observer_state', 'monero_transfer_observations', 'monero_observation_events', 'monero_observation_scans']) {
|
||||
assert.ok((await admin.query('SELECT to_regclass($1) AS name', [`wk_custody.${table}`])).rows[0].name);
|
||||
}
|
||||
assert.ok((await admin.query("SELECT to_regclass('wk_custody.monero_deposit_allocations') AS name")).rows[0].name);
|
||||
assert.ok((await admin.query("SELECT to_regclass('wk_custody.pilot_custody_identity') AS name")).rows[0].name);
|
||||
for (const table of ['monero_deposit_credit_events', 'monero_deposit_reorg_holds',
|
||||
'monero_deposit_release_events', 'monero_deposit_reorg_resolutions']) {
|
||||
assert.ok((await admin.query('SELECT to_regclass($1) AS name', [`wk_custody.${table}`])).rows[0].name);
|
||||
@@ -233,7 +235,7 @@ test('custody schema v1 upgrades additively through v9 without dropping existing
|
||||
} finally { await admin.end(); }
|
||||
});
|
||||
|
||||
test('custody schema v2 upgrades explicitly through v9 deposit and withdrawal lifecycle tables', async t => {
|
||||
test('custody schema v2 upgrades explicitly through v10 deposit and withdrawal lifecycle tables', async t => {
|
||||
const admin = new Pool(config);
|
||||
await admin.query('DROP SCHEMA IF EXISTS wk_custody CASCADE');
|
||||
const client = await admin.connect();
|
||||
@@ -246,14 +248,82 @@ test('custody schema v2 upgrades explicitly through v9 deposit and withdrawal li
|
||||
await client.query('COMMIT');
|
||||
await migrateCustody(admin); await migrateCustody(admin);
|
||||
const versions = await admin.query('SELECT version FROM wk_custody.schema_versions ORDER BY version');
|
||||
assert.deepEqual(versions.rows.map(row => Number(row.version)), [1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
assert.deepEqual(versions.rows.map(row => Number(row.version)), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
assert.equal((await admin.query("SELECT value FROM wk_custody.custody_meta WHERE key='v2-marker'")).rows[0].value, 'preserve');
|
||||
assert.ok((await admin.query("SELECT to_regclass('wk_custody.monero_deposit_release_events') AS name")).rows[0].name);
|
||||
assert.ok((await admin.query("SELECT to_regclass('wk_custody.monero_withdrawal_intents') AS name")).rows[0].name);
|
||||
assert.ok((await admin.query("SELECT to_regclass('wk_custody.pilot_custody_identity') AS name")).rows[0].name);
|
||||
} catch (error) { await client.query('ROLLBACK').catch(() => {}); throw error; }
|
||||
finally { client.release(); await admin.end(); }
|
||||
});
|
||||
|
||||
test('pilot custody identity binds the private market chain to Monero Mainnet without enabling funds', async t => {
|
||||
assert.equal(parsePilotCustodianId('AAAAAAAA-AAAA-4AAA-8AAA-AAAAAAAAAAAA'), 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa');
|
||||
assert.throws(() => parsePilotCustodianId('not-a-uuid'), /Invalid pilot custodian UUID/);
|
||||
const admin = new Pool(config), database = `pilot_identity_${randomUUID().replaceAll('-', '')}`;
|
||||
await admin.query(`CREATE DATABASE "${database}"`);
|
||||
const target = new Pool({ ...config, database });
|
||||
const run = promisify(execFile), custodianId = randomUUID(), runtimeRole = `pilot_identity_${randomUUID().replaceAll('-', '')}`;
|
||||
const code = `import { Pool } from 'pg';
|
||||
import { initializePilotCustodyIdentity } from './server/market/pilot-custody-identity.ts';
|
||||
const pool=new Pool({host:'127.0.0.1',database:process.env.TEST_DATABASE,user:'postgres',ssl:false});
|
||||
try { console.log(JSON.stringify(await initializePilotCustodyIdentity(pool,process.env.TEST_CUSTODIAN_ID,1234))); }
|
||||
finally { await pool.end(); }`;
|
||||
const env = { ...process.env, WIKIDECK_NETWORK: 'pilot', WIKIDECK_PILOT_MODE: 'private-mock-only',
|
||||
TEST_DATABASE: database, TEST_CUSTODIAN_ID: custodianId };
|
||||
try {
|
||||
await migrateCustody(target);
|
||||
await admin.query(`CREATE ROLE "${runtimeRole}" LOGIN`);
|
||||
assert.equal((await target.query('SELECT has_table_privilege($1,$2,$3) AS allowed',
|
||||
[runtimeRole, 'wk_custody.pilot_custody_identity', 'SELECT'])).rows[0].allowed, false);
|
||||
const first = JSON.parse((await run(process.execPath, ['--experimental-strip-types', '--input-type=module', '-e', code], { env })).stdout.trim());
|
||||
const replay = JSON.parse((await run(process.execPath, ['--experimental-strip-types', '--input-type=module', '-e', code], { env })).stdout.trim());
|
||||
assert.equal(first.mode, 'pilot-custody');
|
||||
assert.equal(first.marketNetwork, 'wikideck-randomx-pilot-1');
|
||||
assert.equal(first.moneroNetwork, 'mainnet');
|
||||
assert.equal(first.activationStatus, 'identity-only');
|
||||
assert.equal(first.custodianId, custodianId);
|
||||
assert.deepEqual(replay, first);
|
||||
await assert.rejects(run(process.execPath, ['--experimental-strip-types', '--input-type=module', '-e', code], {
|
||||
env: { ...env, TEST_CUSTODIAN_ID: randomUUID() },
|
||||
}));
|
||||
await assert.rejects(run(process.execPath, ['--experimental-strip-types', '--input-type=module', '-e', code], {
|
||||
env: { ...env, WIKIDECK_NETWORK: 'testnet' },
|
||||
}));
|
||||
const stored = await target.query('SELECT * FROM wk_custody.pilot_custody_identity');
|
||||
assert.equal(stored.rowCount, 1);
|
||||
assert.equal((await target.query('SELECT count(*)::int AS n FROM wk_custody.journals')).rows[0].n, 0);
|
||||
assert.equal((await target.query('SELECT count(*)::int AS n FROM wk_custody.monero_deposit_allocations')).rows[0].n, 0);
|
||||
assert.equal((await target.query('SELECT count(*)::int AS n FROM wk_custody.monero_withdrawal_intents')).rows[0].n, 0);
|
||||
assert.equal((await target.query("SELECT count(*)::int AS n FROM wk_custody.custody_meta WHERE key='identity'")).rows[0].n, 0);
|
||||
} finally {
|
||||
await target.end();
|
||||
await admin.query(`DROP DATABASE IF EXISTS "${database}" WITH (FORCE)`);
|
||||
await admin.query(`DROP ROLE IF EXISTS "${runtimeRole}"`);
|
||||
await admin.end();
|
||||
}
|
||||
});
|
||||
|
||||
test('pilot custody identity refuses a database containing pre-existing mock or financial data', async t => {
|
||||
const admin = new Pool(config), database = `pilot_identity_dirty_${randomUUID().replaceAll('-', '')}`;
|
||||
await admin.query(`CREATE DATABASE "${database}"`);
|
||||
const target = new Pool({ ...config, database }), run = promisify(execFile);
|
||||
try {
|
||||
await migrateCustody(target);
|
||||
await target.query("INSERT INTO wk_custody.accounts(id,normal) VALUES('pre-existing-mock','credit')");
|
||||
const code = `import { Pool } from 'pg';
|
||||
import { initializePilotCustodyIdentity } from './server/market/pilot-custody-identity.ts';
|
||||
const p=new Pool({host:'127.0.0.1',database:process.env.TEST_DATABASE,user:'postgres',ssl:false});
|
||||
try { await initializePilotCustodyIdentity(p,process.env.TEST_CUSTODIAN_ID,1234); }
|
||||
finally { await p.end(); }`;
|
||||
await assert.rejects(run(process.execPath, ['--experimental-strip-types', '--input-type=module', '-e', code], {
|
||||
env: { ...process.env, WIKIDECK_NETWORK: 'pilot', WIKIDECK_PILOT_MODE: 'private-mock-only',
|
||||
TEST_DATABASE: database, TEST_CUSTODIAN_ID: randomUUID() },
|
||||
}), /separate empty custody database/);
|
||||
assert.equal((await target.query('SELECT count(*)::int AS n FROM wk_custody.pilot_custody_identity')).rows[0].n, 0);
|
||||
} finally { await target.end(); await admin.query(`DROP DATABASE IF EXISTS "${database}" WITH (FORCE)`); await admin.end(); }
|
||||
});
|
||||
|
||||
test('mainnet custody identity bootstrap is one-time, chain-bound, and does not open withdrawals', async t => {
|
||||
assert.equal(parseMainnetCustodianId('AAAAAAAA-AAAA-4AAA-8AAA-AAAAAAAAAAAA'), 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa');
|
||||
assert.throws(() => parseMainnetCustodianId('not-a-uuid'), /Invalid mainnet custodian UUID/);
|
||||
|
||||
Reference in New Issue
Block a user