mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
116 lines
4.3 KiB
JavaScript
116 lines
4.3 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const { spawnSync } = require('node:child_process');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const { test } = require('node:test');
|
|
|
|
const SCRIPT = path.resolve(
|
|
__dirname,
|
|
'../../scripts/ql3-postgres-prompt-output-recovery-live-contract.cjs',
|
|
);
|
|
const { IMAGE } = require(SCRIPT);
|
|
|
|
test('pins the PostgreSQL 18 image by reviewed OCI digest', () => {
|
|
assert.equal(
|
|
IMAGE,
|
|
'docker.io/library/postgres:18@sha256:3a82e1f56c8f0f5616a11103ac3d47e632c3938698946a7ad26da0df1334744a',
|
|
);
|
|
});
|
|
|
|
test('refuses Docker mutation unless the live gate is explicitly enabled', () => {
|
|
const env = { ...process.env };
|
|
delete env.QL3_RUN_POSTGRES_BACKUP_RECOVERY_LIVE;
|
|
const result = spawnSync(process.execPath, [SCRIPT], {
|
|
env,
|
|
encoding: 'utf8',
|
|
timeout: 10_000,
|
|
});
|
|
assert.equal(result.status, 1);
|
|
assert.match(
|
|
result.stderr,
|
|
/QL3_RUN_POSTGRES_BACKUP_RECOVERY_LIVE=true is required/,
|
|
);
|
|
assert.doesNotMatch(result.stderr, /Docker command failed/);
|
|
});
|
|
|
|
test('keeps source and restore on loopback-only random database ports', () => {
|
|
const source = fs.readFileSync(SCRIPT, 'utf8');
|
|
assert.match(source, /'--publish',\s*'127\.0\.0\.1::5432'/);
|
|
assert.match(source, /mapping\.match\(\/\^127\\\.0\\\.0\\\.1:/);
|
|
assert.doesNotMatch(source, /0\.0\.0\.0::5432/);
|
|
assert.match(source, /'--command',\s*'SELECT 1'/);
|
|
assert.match(source, /Atomics\.wait/);
|
|
assert.doesNotMatch(source, /'pg_isready'/);
|
|
assert.match(source, /'pg_dump'/);
|
|
assert.match(source, /'--format',\s*'custom'/);
|
|
assert.match(source, /'pg_restore'/);
|
|
assert.match(source, /'--exit-on-error'/);
|
|
const sourceRemoval = source.indexOf(
|
|
"docker(['rm', '--force', '--volumes', sourceContainer])",
|
|
);
|
|
const restoreStart = source.indexOf(
|
|
'startPostgres(restoreContainer, password)',
|
|
);
|
|
assert.ok(sourceRemoval >= 0);
|
|
assert.ok(restoreStart > sourceRemoval);
|
|
assert.match(source, /sourceContainerRemovedBeforeRestore: true/);
|
|
assert.match(source, /sourceAndRestoreContainerIdsDiffer:/);
|
|
});
|
|
|
|
test('exports only restored exact facts into the existing offline verifier', () => {
|
|
const source = fs.readFileSync(SCRIPT, 'utf8');
|
|
assert.match(
|
|
source,
|
|
/const restoredEvidence = await readProductionEvidence\(/,
|
|
);
|
|
assert.match(source, /assert\.equal\(restoredRowDigest, sourceRowDigest\)/);
|
|
assert.match(source, /JSON\.stringify\(restoredEvidence\.durableKeyFact\)/);
|
|
assert.match(source, /JSON\.stringify\(restoredEvidence\.artifact\)/);
|
|
assert.match(source, /runClusterPromptOutputExternalRecoveryVerifier/);
|
|
assert.match(source, /disposeClusterPromptOutputExternalRecoveryInput/);
|
|
assert.match(source, /backupContainsNoPlaintextOrRawKey: true/);
|
|
assert.match(source, /productionMigrationHistoryRestoredExactly: true/);
|
|
assert.match(
|
|
source,
|
|
/productionRotationAndArtifactRepositoriesReopened: true/,
|
|
);
|
|
assert.match(source, /reportIsContentFree: true/);
|
|
});
|
|
|
|
test('uses the QL3 production migration and Prompt persistence lineage', () => {
|
|
const source = fs.readFileSync(SCRIPT, 'utf8');
|
|
assert.match(source, /runPostgresMigrations/);
|
|
assert.match(source, /migratePostgresModelInvocationFeature/);
|
|
assert.match(source, /createPluginPackagePromptAdmissionBundle/);
|
|
assert.match(source, /PostgresModelInvocationRepository/);
|
|
assert.match(source, /PostgresPluginPackagePromptOutputArtifactRepository/);
|
|
assert.match(
|
|
source,
|
|
/PostgresPluginPackagePromptOutputKeyRotationRepository/,
|
|
);
|
|
assert.match(source, /model_invocation_prompt_admissions/);
|
|
assert.match(source, /model_invocation_prompt_output_artifacts/);
|
|
assert.match(
|
|
source,
|
|
/model_invocation_prompt_output_key_rotation_completions/,
|
|
);
|
|
assert.doesNotMatch(source, /ql3_recovery\.prompt_output_evidence/);
|
|
});
|
|
|
|
test('always removes both disposable containers, volumes and private files', () => {
|
|
const source = fs.readFileSync(SCRIPT, 'utf8');
|
|
assert.match(
|
|
source,
|
|
/docker\(\['rm', '--force', '--volumes', sourceContainer\]/,
|
|
);
|
|
assert.match(
|
|
source,
|
|
/docker\(\['rm', '--force', '--volumes', restoreContainer\]/,
|
|
);
|
|
assert.match(
|
|
source,
|
|
/rmSync\(directory, \{ recursive: true, force: true \}\)/,
|
|
);
|
|
assert.doesNotMatch(source, /ql3-cnpg-evidence-control-plane/);
|
|
});
|