Add ARCHY_TEST_PACKAGE=gashboard with hardcoded Node test entry, synthetic data settings, private network/PID namespace and wallet/container/app tmpfs masks. Reject arbitrary command arguments and conflicting fixture modes; keep existing Rust/C01/container paths intact. Retain only the Rust runner DAC traversal capability for the read-only worktree. Six runner regressions pass, including existing modes; update the existing C01 test sudo mock for its exec-profile inventory call. Nine actual Gashboard API regressions pass in the new isolated systemd namespace with patched Zod/Express dependencies. Initial namespace file-access failure preserved before aligning traversal capability. No production app entry or installed service was run.
27 lines
1.7 KiB
JavaScript
27 lines
1.7 KiB
JavaScript
// Fixed target, with a runtime guard before importing any application/test code.
|
|
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import { spawnSync } from 'node:child_process'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
assert.equal(process.env.ARCHY_TEST_ISOLATED, '1', 'requires the backend isolation runner')
|
|
assert.equal(process.pid, 1, 'requires a private PID namespace')
|
|
const mounts = readFileSync('/proc/self/mountinfo', 'utf8')
|
|
for (const directory of ['/run', '/var/lib/archipelago', '/var/lib/containers', '/tmp', '/data', '/app']) {
|
|
assert(mounts.split('\n').some(line => line.split(' ')[4] === directory && line.split(' - ')[1]?.startsWith('tmpfs ')), `requires private tmpfs at ${directory}`)
|
|
}
|
|
const api = fileURLToPath(new URL('../../docker/gashboard/apps/api/', import.meta.url))
|
|
const tests = ['access', 'chat', 'display-name', 'parse', 'recovery'].map(name => `tests/${name}.test.ts`)
|
|
const result = spawnSync(process.execPath, ['--import', 'tsx', '--test', '--test-concurrency=1', ...tests], {
|
|
cwd: api, stdio: 'inherit',
|
|
env: { ...process.env, NODE_ENV: 'test', LOG_LEVEL: 'silent', NODE_OPTIONS: '', TSX_DISABLE_CACHE: '1',
|
|
JWT_SECRET: 'isolated-gashboard-test-secret-only-32-characters', DATUM_ADMIN_PASSWORD: 'isolated-test-only',
|
|
NOSTR_OWNER_PUBKEYS: 'a'.repeat(64), NOSTR_ALLOWED_NPUBS: '',
|
|
CONTRIBUTION_LEDGER_PATH: '/data/contribution-ledger.json', CHAT_STORE_PATH: '/data/chat.json',
|
|
ACCESS_LIST_PATH: '/data/access.json', ARCHIPELAGO_PROVIDER_PATH: '/data/provider.js',
|
|
DATUM_URL: 'http://127.0.0.1:1', MEMPOOL_API_URL: 'http://127.0.0.1:1',
|
|
},
|
|
})
|
|
if (result.error) throw result.error
|
|
process.exit(result.status ?? 1)
|