mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
Extracted duplicated target path resolution and allowlist validation logic into a shared `resolveAndValidateTarget` helper function in `src/services/governance/index.js`. Updated `createProposal`, `validateProposal`, `applyProposal`, and `rollbackPrompt` to use the new helper, ensuring consistent validation and path handling across the service. Added `test/governance-health.test.mjs` to verify validation logic. Co-authored-by: PR0M3TH3AN <[email protected]>
70 lines
2.2 KiB
JavaScript
70 lines
2.2 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { createProposal, validateProposal } from '../src/services/governance/index.js';
|
|
import path from 'node:path';
|
|
import fs from 'node:fs/promises';
|
|
|
|
test('createProposal should throw error for disallowed target', async () => {
|
|
const agent = 'test-agent';
|
|
const target = 'secrets/passwords.txt';
|
|
const newContent = 'new content';
|
|
|
|
await assert.rejects(
|
|
createProposal({ agent, target, newContent, reason: 'test' }),
|
|
{
|
|
message: /Target secrets\/passwords.txt is not in an allowed directory/
|
|
}
|
|
);
|
|
});
|
|
|
|
test('validateProposal should return invalid for disallowed target', async () => {
|
|
const id = 'test-disallowed-proposal';
|
|
const dir = path.resolve(process.cwd(), 'src/proposals', id);
|
|
await fs.mkdir(dir, { recursive: true });
|
|
|
|
const meta = {
|
|
id,
|
|
author: 'test-agent',
|
|
target: 'secrets/passwords.txt',
|
|
reason: 'test',
|
|
timestamp: new Date().toISOString(),
|
|
status: 'pending'
|
|
};
|
|
|
|
await fs.writeFile(path.join(dir, 'meta.json'), JSON.stringify(meta));
|
|
await fs.writeFile(path.join(dir, 'new.md'), 'Shared contract (required):\nRequired startup + artifacts + memory + issue capture');
|
|
|
|
try {
|
|
const result = await validateProposal(id);
|
|
assert.strictEqual(result.valid, false);
|
|
assert.strictEqual(result.reason, 'Target not in allowed directories.');
|
|
} finally {
|
|
await fs.rm(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('validateProposal should return valid for allowed target', async () => {
|
|
const id = 'test-allowed-proposal';
|
|
const dir = path.resolve(process.cwd(), 'src/proposals', id);
|
|
await fs.mkdir(dir, { recursive: true });
|
|
|
|
const meta = {
|
|
id,
|
|
author: 'test-agent',
|
|
target: 'src/prompts/daily/test.md',
|
|
reason: 'test',
|
|
timestamp: new Date().toISOString(),
|
|
status: 'pending'
|
|
};
|
|
|
|
await fs.writeFile(path.join(dir, 'meta.json'), JSON.stringify(meta));
|
|
await fs.writeFile(path.join(dir, 'new.md'), 'Shared contract (required):\nRequired startup + artifacts + memory + issue capture');
|
|
|
|
try {
|
|
const result = await validateProposal(id);
|
|
assert.strictEqual(result.valid, true);
|
|
} finally {
|
|
await fs.rm(dir, { recursive: true, force: true });
|
|
}
|
|
});
|