mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-21 01:32:44 +08:00
335 lines
10 KiB
JavaScript
335 lines
10 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const { spawnSync } = require('node:child_process');
|
|
const { test } = require('node:test');
|
|
const {
|
|
LocalOwnerGcCliConfigurationError,
|
|
createLocalOwnerGcCommandRunner,
|
|
} = require('@qinglong/local-owner-maintenance/command');
|
|
const {
|
|
pluginPackagePromptOutputArtifactRetentionPolicyDigest,
|
|
} = require('../../ql3-ai/dist/prompt-output/pluginPackagePromptOutputArtifact');
|
|
|
|
function privateCommand(t, value) {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-owner-gc-cli-'));
|
|
const filePath = path.join(root, 'command.json');
|
|
fs.writeFileSync(filePath, `${JSON.stringify(value)}\n`, { mode: 0o600 });
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
return filePath;
|
|
}
|
|
|
|
function acknowledgementCommand(overrides = {}) {
|
|
return {
|
|
schemaVersion: 1,
|
|
operation: 'owner.delivery-acknowledgement.compact',
|
|
options: {
|
|
databasePath: '/private/ql3.sqlite',
|
|
profile: 'edge',
|
|
secretDeliveryDirectory: '/private/secrets',
|
|
retentionPolicy: {
|
|
version: 1,
|
|
replayRetentionMs: 2_592_000_000,
|
|
auditRetentionMs: 2_592_000_000,
|
|
},
|
|
},
|
|
request: {
|
|
mutationId: '00000000-0000-4000-8000-000000000a02',
|
|
requestId: 'gc-a02',
|
|
acknowledgementMutationId: '00000000-0000-4000-8000-000000000a01',
|
|
expectedKind: 'credential',
|
|
expectedDeliveryDigest: 'd'.repeat(64),
|
|
},
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function dependencies(state) {
|
|
return {
|
|
async openAcknowledgementGc(options) {
|
|
state.ackOptions = options;
|
|
return {
|
|
profile: 'edge',
|
|
async compact(request) {
|
|
state.ackRequest = request;
|
|
return {
|
|
status: 'inserted',
|
|
record: {
|
|
mutationId: request.mutationId,
|
|
requestId: request.requestId,
|
|
acknowledgementMutationId: request.acknowledgementMutationId,
|
|
acknowledgementKind: request.expectedKind,
|
|
deliveryDigest: request.expectedDeliveryDigest,
|
|
acknowledgedAtMs: 100,
|
|
acknowledgementSemanticDigest: 'a'.repeat(64),
|
|
bridgeClearEvidenceDigest: 'b'.repeat(64),
|
|
retentionPolicy: options.retentionPolicy,
|
|
retentionPolicyDigest: 'c'.repeat(64),
|
|
retentionEligibleAtMs: 200,
|
|
compactedAtMs: 300,
|
|
},
|
|
};
|
|
},
|
|
async close() {
|
|
state.ackClosed = true;
|
|
},
|
|
};
|
|
},
|
|
async openPepperMaterialGc(options) {
|
|
state.pepperOptions = options;
|
|
return {
|
|
profile: 'standalone',
|
|
async collect(request) {
|
|
state.pepperRequest = request;
|
|
return {
|
|
status: 'existing',
|
|
record: {
|
|
prepareMutationId: request.prepareMutationId,
|
|
prepareRequestId: request.prepareRequestId,
|
|
pepperKeyId: request.pepperKeyId,
|
|
materialDigest: 'a'.repeat(64),
|
|
backupMaterialDigest: 'b'.repeat(64),
|
|
activePepperKeyId: 'active-v2',
|
|
activeGeneration: 2,
|
|
activeMaterialDigest: 'c'.repeat(64),
|
|
retentionPolicy: options.retentionPolicy,
|
|
retentionPolicyDigest: 'd'.repeat(64),
|
|
referencesInspectedAtMs: 100,
|
|
retentionEligibleAtMs: 200,
|
|
preparedAtMs: 300,
|
|
state: 'completed',
|
|
completeMutationId: request.completeMutationId,
|
|
completeRequestId: request.completeRequestId,
|
|
destructionProofDigest: 'e'.repeat(64),
|
|
completedAtMs: 400,
|
|
},
|
|
runtimeMaterial: {},
|
|
backupMaterial: {},
|
|
};
|
|
},
|
|
async close() {
|
|
state.pepperClosed = true;
|
|
},
|
|
};
|
|
},
|
|
async openPromptOutputGc(options) {
|
|
state.promptOptions = options;
|
|
return {
|
|
profile: options.profile,
|
|
async collect() {
|
|
state.promptCollected = true;
|
|
return {
|
|
scanned: 3,
|
|
tombstoned: 2,
|
|
skipped: 1,
|
|
hasMore: false,
|
|
};
|
|
},
|
|
async close() {
|
|
state.promptClosed = true;
|
|
},
|
|
};
|
|
},
|
|
async openPromptOutputKeyRetirement(options) {
|
|
state.promptKeyOptions = options;
|
|
return {
|
|
profile: options.profile,
|
|
async retire(request) {
|
|
state.promptKeyRequest = request;
|
|
return {
|
|
status: 'completed',
|
|
keyId: request.keyId,
|
|
retirementId: request.retirementId,
|
|
preparationDigest: 'e'.repeat(64),
|
|
completionDigest: 'f'.repeat(64),
|
|
completedAtMs: 500,
|
|
};
|
|
},
|
|
async close() {
|
|
state.promptKeyClosed = true;
|
|
},
|
|
};
|
|
},
|
|
};
|
|
}
|
|
|
|
test('runs acknowledgement compaction from one private durable command file', async (t) => {
|
|
const state = {};
|
|
const command = acknowledgementCommand();
|
|
const result = await createLocalOwnerGcCommandRunner(dependencies(state)).run(
|
|
privateCommand(t, command),
|
|
);
|
|
assert.deepEqual(result, {
|
|
schemaVersion: 1,
|
|
operation: command.operation,
|
|
status: 'inserted',
|
|
gcMutationId: command.request.mutationId,
|
|
acknowledgementMutationId: command.request.acknowledgementMutationId,
|
|
acknowledgementKind: 'credential',
|
|
retentionEligibleAtMs: 200,
|
|
compactedAtMs: 300,
|
|
});
|
|
assert.deepEqual(state.ackOptions, command.options);
|
|
assert.deepEqual(state.ackRequest, command.request);
|
|
assert.equal(state.ackClosed, true);
|
|
});
|
|
|
|
test('runs pepper material collection without exposing destruction digests', async (t) => {
|
|
const state = {};
|
|
const command = {
|
|
schemaVersion: 1,
|
|
operation: 'owner.pepper-material.collect',
|
|
options: {
|
|
databasePath: '/private/ql3.sqlite',
|
|
profile: 'standalone',
|
|
keyringDirectory: '/private/keyring',
|
|
backupDirectory: '/backup/keyring',
|
|
retentionPolicy: {
|
|
version: 1,
|
|
acknowledgementRetentionMs: 604_800_000,
|
|
auditRetentionMs: 2_592_000_000,
|
|
backupRetentionMs: 2_592_000_000,
|
|
},
|
|
},
|
|
request: {
|
|
prepareMutationId: '00000000-0000-4000-8000-000000000b01',
|
|
prepareRequestId: 'gc-b01',
|
|
completeMutationId: '00000000-0000-4000-8000-000000000b02',
|
|
completeRequestId: 'gc-b02',
|
|
pepperKeyId: 'retired-v1',
|
|
},
|
|
};
|
|
const result = await createLocalOwnerGcCommandRunner(dependencies(state)).run(
|
|
privateCommand(t, command),
|
|
);
|
|
assert.deepEqual(result, {
|
|
schemaVersion: 1,
|
|
operation: command.operation,
|
|
status: 'existing',
|
|
prepareMutationId: command.request.prepareMutationId,
|
|
completeMutationId: command.request.completeMutationId,
|
|
pepperKeyId: command.request.pepperKeyId,
|
|
state: 'completed',
|
|
completedAtMs: 400,
|
|
});
|
|
assert.equal('destructionProofDigest' in result, false);
|
|
assert.equal(state.pepperClosed, true);
|
|
});
|
|
|
|
test('runs one bounded Prompt output collection without returning policy data', async (t) => {
|
|
const state = {};
|
|
const policy = { revision: 'retention-v1', retentionMs: 3_600_000 };
|
|
const command = {
|
|
schemaVersion: 1,
|
|
operation: 'owner.prompt-output.collect',
|
|
options: {
|
|
databasePath: '/private/ql3.sqlite',
|
|
profile: 'edge',
|
|
limit: 4,
|
|
retentionPolicyCatalog: {
|
|
schemaVersion: 1,
|
|
policies: [
|
|
{
|
|
projectId: 'project-a',
|
|
policy,
|
|
policyDigest:
|
|
pluginPackagePromptOutputArtifactRetentionPolicyDigest(policy),
|
|
},
|
|
],
|
|
},
|
|
},
|
|
request: {},
|
|
};
|
|
const result = await createLocalOwnerGcCommandRunner(dependencies(state)).run(
|
|
privateCommand(t, command),
|
|
);
|
|
assert.deepEqual(result, {
|
|
schemaVersion: 1,
|
|
operation: command.operation,
|
|
scanned: 3,
|
|
tombstoned: 2,
|
|
skipped: 1,
|
|
hasMore: false,
|
|
});
|
|
assert.deepEqual(state.promptOptions, command.options);
|
|
assert.equal(state.promptCollected, true);
|
|
assert.equal(state.promptClosed, true);
|
|
assert.equal('retentionPolicyCatalog' in result, false);
|
|
});
|
|
|
|
test('retires one Prompt output key without returning key material', async (t) => {
|
|
const state = {};
|
|
const command = {
|
|
schemaVersion: 1,
|
|
operation: 'owner.prompt-output-key.retire',
|
|
options: {
|
|
databasePath: '/private/ql3.sqlite',
|
|
profile: 'edge',
|
|
keyringPath: '/private/prompt-output-keyring.json',
|
|
},
|
|
request: {
|
|
keyId: 'qlpo-retired',
|
|
retirementId: 'retirement-a',
|
|
requestId: 'request-a',
|
|
mutationId: 'mutation-a',
|
|
},
|
|
};
|
|
const result = await createLocalOwnerGcCommandRunner(dependencies(state)).run(
|
|
privateCommand(t, command),
|
|
);
|
|
assert.deepEqual(result, {
|
|
schemaVersion: 1,
|
|
operation: command.operation,
|
|
status: 'completed',
|
|
keyId: command.request.keyId,
|
|
retirementId: command.request.retirementId,
|
|
preparationDigest: 'e'.repeat(64),
|
|
completionDigest: 'f'.repeat(64),
|
|
completedAtMs: 500,
|
|
});
|
|
assert.deepEqual(state.promptKeyOptions, command.options);
|
|
assert.deepEqual(state.promptKeyRequest, command.request);
|
|
assert.equal(state.promptKeyClosed, true);
|
|
assert.equal(JSON.stringify(result).includes('material'), false);
|
|
});
|
|
|
|
test('rejects widened or non-private command files before opening authority', async (t) => {
|
|
const state = {};
|
|
const runner = createLocalOwnerGcCommandRunner(dependencies(state));
|
|
const widened = privateCommand(t, acknowledgementCommand({ now: 1 }));
|
|
await assert.rejects(runner.run(widened), LocalOwnerGcCliConfigurationError);
|
|
const broad = privateCommand(t, acknowledgementCommand());
|
|
fs.chmodSync(broad, 0o644);
|
|
await assert.rejects(runner.run(broad), LocalOwnerGcCliConfigurationError);
|
|
assert.equal(state.ackOptions, undefined);
|
|
assert.equal(state.pepperOptions, undefined);
|
|
assert.equal(state.promptOptions, undefined);
|
|
});
|
|
|
|
test('binary has a bounded command-file-only interface', () => {
|
|
const help = spawnSync(
|
|
process.execPath,
|
|
[path.join(__dirname, '../dist/cli.js'), '--help'],
|
|
{
|
|
encoding: 'utf8',
|
|
},
|
|
);
|
|
assert.equal(help.status, 0);
|
|
assert.match(help.stdout, /^Usage: ql3-owner-gc run --command-file /);
|
|
assert.equal(help.stderr, '');
|
|
const invalid = spawnSync(
|
|
process.execPath,
|
|
[path.join(__dirname, '../dist/cli.js'), 'run'],
|
|
{
|
|
encoding: 'utf8',
|
|
},
|
|
);
|
|
assert.equal(invalid.status, 64);
|
|
assert.equal(invalid.stdout, '');
|
|
assert.equal(
|
|
JSON.parse(invalid.stderr).code,
|
|
'LOCAL_OWNER_GC_CLI_USAGE_INVALID',
|
|
);
|
|
});
|