Skip to content

Commit b5c3a7d

Browse files
committed
refactor(extension): Update vat command validation logic
1 parent fbda254 commit b5c3a7d

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

packages/extension/src/kernel-integration/handlers/send-vat-command.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { object } from '@metamask/superstruct';
2+
import type { Infer } from '@metamask/superstruct';
23
import { UnsafeJsonStruct } from '@metamask/utils';
34
import type { Json } from '@metamask/utils';
45
import { VatIdStruct } from '@ocap/kernel';
@@ -17,6 +18,8 @@ export const sendVatCommandSpec: MethodSpec<
1718
result: object({ result: UnsafeJsonStruct }),
1819
};
1920

21+
export type SendVatCommandParams = Infer<(typeof sendVatCommandSpec)['params']>;
22+
2023
export type SendVatCommandHooks = {
2124
kernel: Pick<Kernel, 'sendVatCommand'>;
2225
};
@@ -34,3 +37,14 @@ export const sendVatCommandHandler: Handler<
3437
return { result };
3538
},
3639
};
40+
41+
/**
42+
* Asserts that the given params are valid for the `sendVatCommand` method.
43+
*
44+
* @param params - The params to assert.
45+
*/
46+
export function assertVatCommandParams(
47+
params: unknown,
48+
): asserts params is SendVatCommandParams {
49+
sendVatCommandSpec.params.assert(params);
50+
}

packages/extension/src/ui/hooks/useKernelActions.test.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import { describe, it, expect, vi, beforeEach } from 'vitest';
33

44
import clusterConfig from '../../vats/default-cluster.json';
55

6+
vi.mock('../../kernel-integration/handlers/send-vat-command.ts', () => ({
7+
assertVatCommandParams: vi.fn(),
8+
}));
9+
610
vi.mock('../context/PanelContext.tsx', () => ({
711
usePanelContext: vi.fn(),
812
}));
@@ -15,7 +19,7 @@ vi.mock('@ocap/utils', async (importOriginal) => ({
1519
describe('useKernelActions', () => {
1620
const mockSendMessage = vi.fn();
1721
const mockLogMessage = vi.fn();
18-
const mockMessageContent = '{"test": "content"}';
22+
const mockMessageContent = '{"id": "v0", "payload": {"method": "test"}}';
1923

2024
beforeEach(async () => {
2125
const { usePanelContext } = await import('../context/PanelContext.tsx');
@@ -35,13 +39,15 @@ describe('useKernelActions', () => {
3539
it('sends message with payload', async () => {
3640
const { useKernelActions } = await import('./useKernelActions.ts');
3741
const { result } = renderHook(() => useKernelActions());
38-
const expectedParams = { test: 'content' };
3942
mockSendMessage.mockResolvedValueOnce({ success: true });
4043
result.current.sendKernelCommand();
4144
await waitFor(() => {
4245
expect(mockSendMessage).toHaveBeenCalledWith({
4346
method: 'sendVatCommand',
44-
params: expectedParams,
47+
params: expect.objectContaining({
48+
id: 'v0',
49+
payload: expect.any(Object),
50+
}),
4551
});
4652
});
4753
});

packages/extension/src/ui/hooks/useKernelActions.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import type { ClusterConfig } from '@ocap/kernel';
33
import { stringify } from '@ocap/utils';
44
import { useCallback } from 'react';
55

6+
import { assertVatCommandParams } from '../../kernel-integration/handlers/send-vat-command.ts';
7+
import type { SendVatCommandParams } from '../../kernel-integration/handlers/send-vat-command.ts';
68
import { usePanelContext } from '../context/PanelContext.tsx';
79
import { nextMessageId } from '../utils.ts';
810

@@ -28,7 +30,7 @@ export function useKernelActions(): {
2830
const sendKernelCommand = useCallback(() => {
2931
callKernelMethod({
3032
method: 'sendVatCommand',
31-
params: coerceCommandParams(JSON.parse(messageContent)),
33+
params: parseCommandParams(messageContent),
3234
})
3335
.then((result) => logMessage(stringify(result, 0), 'received'))
3436
.catch((error) => logMessage(error.message, 'error'));
@@ -129,27 +131,29 @@ export function useKernelActions(): {
129131
}
130132

131133
/**
132-
* Coerces sendVatCommand params to the expected format. Basically, turns the payload
134+
* Parses sendVatCommand params to the expected format. Basically, turns the payload
133135
* into a JSON-RPC request.
134136
*
135-
* @param params - The params to coerce.
136-
* @returns The coerced params.
137+
* @param rawParams - The raw, stringified params to parse.
138+
* @returns The parsed params.
137139
*/
138-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
139-
function coerceCommandParams<Params>(params: Params) {
140+
function parseCommandParams(rawParams: string): SendVatCommandParams {
141+
const params = JSON.parse(rawParams);
140142
if (
141143
isObject(params) &&
142144
isObject(params.payload) &&
143145
hasProperty(params.payload, 'method')
144146
) {
145-
return {
147+
const parsed = {
146148
...params,
147149
payload: {
148150
...params.payload,
149151
id: nextMessageId(),
150152
jsonrpc: '2.0',
151153
},
152154
};
155+
assertVatCommandParams(parsed);
156+
return parsed;
153157
}
154-
return params;
158+
throw new Error('Invalid command params');
155159
}

vitest.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ export default defineConfig({
8282
lines: 98.63,
8383
},
8484
'packages/extension/**': {
85-
statements: 78.73,
86-
functions: 81.15,
87-
branches: 74.1,
88-
lines: 78.72,
85+
statements: 78.71,
86+
functions: 80.72,
87+
branches: 74.82,
88+
lines: 78.7,
8989
},
9090
'packages/kernel/**': {
9191
statements: 89.31,

0 commit comments

Comments
 (0)