140 lines
4.7 KiB
JavaScript
140 lines
4.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
import {
|
|
createFixture,
|
|
managedHandler,
|
|
readGrokConfig,
|
|
runGrokHook,
|
|
startApiServer,
|
|
} from '../test-support/grok-test-helpers.mjs';
|
|
|
|
const prePayload = {
|
|
hookEventName: 'pre_tool_use',
|
|
sessionId: 'session-1',
|
|
cwd: 'C:/project',
|
|
workspaceRoot: 'C:/project',
|
|
toolName: 'run_terminal_command',
|
|
toolInput: { command: 'npm test' },
|
|
toolUseId: 'tool-use-1',
|
|
toolInputTruncated: false,
|
|
timestamp: '2026-07-19T12:00:00Z',
|
|
};
|
|
|
|
test('Grok runtimes enforce active state and preserve success and failure payloads', async () => {
|
|
const api = await startApiServer();
|
|
const fixture = await createFixture({ baseUrl: api.baseUrl });
|
|
try {
|
|
const install = await fixture.install();
|
|
assert.equal(install.code, 0, install.stderr);
|
|
const { config } = await readGrokConfig(fixture.configPath);
|
|
const guard = managedHandler(config, 'PreToolUse');
|
|
const successAudit = managedHandler(config, 'PostToolUse');
|
|
const failureAudit = managedHandler(config, 'PostToolUseFailure');
|
|
|
|
const guardResult = await runGrokHook(
|
|
guard.command,
|
|
JSON.stringify(prePayload),
|
|
fixture,
|
|
{ GROK_HOOK_EVENT: 'injected-command-fragment' },
|
|
);
|
|
assert.equal(guardResult.code, 0, guardResult.stderr);
|
|
assert.equal(guardResult.stdout, '');
|
|
|
|
const successPayload = {
|
|
...prePayload,
|
|
hookEventName: 'post_tool_use',
|
|
toolResult: { output: 'tests passed' },
|
|
toolResultTruncated: false,
|
|
durationMs: 125,
|
|
};
|
|
const success = await runGrokHook(
|
|
successAudit.command,
|
|
JSON.stringify(successPayload),
|
|
fixture,
|
|
);
|
|
assert.equal(success.code, 0, success.stderr);
|
|
|
|
const failurePayload = {
|
|
...prePayload,
|
|
hookEventName: 'post_tool_use_failure',
|
|
toolResult: { error: 'command failed', exitCode: 1 },
|
|
toolResultTruncated: false,
|
|
durationMs: 40,
|
|
};
|
|
const failure = await runGrokHook(
|
|
failureAudit.command,
|
|
JSON.stringify(failurePayload),
|
|
fixture,
|
|
);
|
|
assert.equal(failure.code, 0, failure.stderr);
|
|
|
|
const operations = api.requests
|
|
.filter((request) => request.method === 'POST')
|
|
.map((request) => JSON.parse(request.raw));
|
|
assert.equal(operations.length, 2);
|
|
assert.deepEqual(operations[0].payload, successPayload);
|
|
assert.deepEqual(operations[1].payload, failurePayload);
|
|
assert.equal(operations[0].subject.session_id, 'session-1');
|
|
assert.equal(operations[1].action.tool, 'run_terminal_command');
|
|
} finally {
|
|
await fixture.close();
|
|
await api.close();
|
|
}
|
|
});
|
|
|
|
test('Grok guard emits official deny JSON and exit code 2 for frozen and revoked agents', async (t) => {
|
|
for (const status of ['frozen', 'revoked']) {
|
|
await t.test(status, async () => {
|
|
const api = await startApiServer({ status });
|
|
const fixture = await createFixture({ baseUrl: api.baseUrl });
|
|
try {
|
|
assert.equal((await fixture.install()).code, 0);
|
|
const { config } = await readGrokConfig(fixture.configPath);
|
|
const result = await runGrokHook(
|
|
managedHandler(config, 'PreToolUse').command,
|
|
JSON.stringify(prePayload),
|
|
fixture,
|
|
);
|
|
assert.equal(result.code, 2);
|
|
assert.match(result.stderr, new RegExp(status, 'i'));
|
|
const decision = JSON.parse(result.stdout);
|
|
assert.deepEqual(Object.keys(decision).sort(), ['decision', 'reason']);
|
|
assert.equal(decision.decision, 'deny');
|
|
assert.match(decision.reason, new RegExp(status, 'i'));
|
|
} finally {
|
|
await fixture.close();
|
|
await api.close();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
test('Grok audit runtime records malformed input and API failures', async () => {
|
|
const api = await startApiServer({ operationStatus: 503 });
|
|
const fixture = await createFixture({ baseUrl: api.baseUrl });
|
|
try {
|
|
assert.equal((await fixture.install()).code, 0);
|
|
const { config } = await readGrokConfig(fixture.configPath);
|
|
const command = managedHandler(config, 'PostToolUse').command;
|
|
const malformed = await runGrokHook(command, '{ malformed', fixture);
|
|
assert.equal(malformed.code, 0);
|
|
assert.equal(malformed.stderr, '');
|
|
|
|
const upstream = await runGrokHook(command, JSON.stringify({
|
|
...prePayload,
|
|
hookEventName: 'post_tool_use',
|
|
toolResult: { output: 'test' },
|
|
}), fixture);
|
|
assert.equal(upstream.code, 0);
|
|
assert.equal(upstream.stderr, '');
|
|
const log = await readFile(path.join(fixture.agentDir, 'error.log'), 'utf-8');
|
|
assert.match(log, /invalid JSON/i);
|
|
assert.match(log, /HTTP 503/i);
|
|
} finally {
|
|
await fixture.close();
|
|
await api.close();
|
|
}
|
|
});
|