Private CLI workflow for reviewed depowit operations

This commit is contained in:
2026-10-22 02:09:07 -04:00
parent 05aead39ae
commit 12f80fdc53
7 changed files with 231 additions and 2 deletions
+19
View File
@@ -0,0 +1,19 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { 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)}`]), {
action: 'deposit-prepare-credit', argument: 'a'.repeat(64), extraArgument: `${'b'.repeat(64)}:${'c'.repeat(64)}`,
});
assert.deepEqual(parseCustodyDbArguments(['deposit-prepare-resolve-hold', 'credit-id', 'hold-id']), {
action: 'deposit-prepare-resolve-hold', argument: 'credit-id', extraArgument: 'hold-id',
});
});
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', '']]) {
assert.throws(() => parseCustodyDbArguments(args));
}
});
+58
View File
@@ -0,0 +1,58 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { chmod, mkdtemp, rm, symlink, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { loadMoneroDepositReviewApproval, loadMoneroDepositReviewPolicy } from '../server/market/monero-deposit-review-config.ts';
const owner = 'a'.repeat(64);
async function privateFile(path: string, content: string) {
await writeFile(path, content, { mode: 0o600 });
await chmod(path, 0o600);
}
test('deposit review policy requires an owner-only protected file and strict bounds', async t => {
if (process.platform === 'win32') {
await assert.rejects(loadMoneroDepositReviewPolicy({ WIKIDECK_MONERO_DEPOSIT_REVIEW_POLICY_FILE: 'C:\\private\\policy.json' }), /Invalid or inaccessible/);
return;
}
const directory = await mkdtemp(join(tmpdir(), 'wikideck-deposit-review-'));
t.after(() => rm(directory, { recursive: true, force: true }));
const policyPath = join(directory, 'policy.json');
const env = { WIKIDECK_MONERO_DEPOSIT_REVIEW_POLICY_FILE: policyPath };
const valid = { approvedReviewerOwners: [owner], minimumConfirmations: 10, maximumObservationAgeMs: 120_000 };
await assert.rejects(loadMoneroDepositReviewPolicy({}), /required/);
await privateFile(policyPath, JSON.stringify(valid));
assert.deepEqual(await loadMoneroDepositReviewPolicy(env), valid);
await privateFile(policyPath, JSON.stringify({ ...valid, unexpected: true }));
await assert.rejects(loadMoneroDepositReviewPolicy(env), /Invalid or inaccessible/);
await privateFile(policyPath, JSON.stringify({ ...valid, minimumConfirmations: 2 }));
await assert.rejects(loadMoneroDepositReviewPolicy(env), /Invalid or inaccessible/);
await privateFile(policyPath, JSON.stringify(valid)); await chmod(policyPath, 0o644);
await assert.rejects(loadMoneroDepositReviewPolicy(env), /Invalid or inaccessible/);
await rm(policyPath);
await symlink(join(directory, 'missing-target.json'), policyPath);
await assert.rejects(loadMoneroDepositReviewPolicy(env), /Invalid or inaccessible/);
});
test('deposit approval file loader requires an absolute, bounded, private regular file', async t => {
if (process.platform === 'win32') {
await assert.rejects(loadMoneroDepositReviewApproval('C:\\private\\approval.json'), /Invalid or inaccessible/);
return;
}
const directory = await mkdtemp(join(tmpdir(), 'wikideck-deposit-approval-'));
t.after(() => rm(directory, { recursive: true, force: true }));
const approvalPath = join(directory, 'approval.json');
const approval = { version: 1, signature: 'signed-review-fixture' };
await assert.rejects(loadMoneroDepositReviewApproval('relative-approval.json'), /protected Monero deposit review approval/);
await privateFile(approvalPath, JSON.stringify(approval));
assert.deepEqual(await loadMoneroDepositReviewApproval(approvalPath), approval);
await privateFile(approvalPath, 'x'.repeat(64 * 1024 + 1));
await assert.rejects(loadMoneroDepositReviewApproval(approvalPath), /protected Monero deposit review approval/);
await privateFile(approvalPath, '{malformed');
await assert.rejects(loadMoneroDepositReviewApproval(approvalPath), /protected Monero deposit review approval/);
});