Files
memind/mindspace-mcp-scoped-token.test.mjs
T
John ce2a4b0e1a
Memind CI / Test, build, and release guards (push) Has been cancelled
feat(intent): 歧义任务走 LLM 路由,并在选中 agent 时离开直聊会话
对比/清单/行程等口吻按人群场景交给分类器;本机 .env 可覆盖 admin-db 的 router 开关。
顺带在 MindSpace MCP token 过期时轮换 Goose 会话,避免旧会话空 Finish。
2026-09-12 11:07:45 +08:00

154 lines
3.6 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
mintMindSpaceMcpScopedToken,
mindSpaceMcpScopedTokenNeedsRotation,
peekMindSpaceMcpScopedTokenExpiryMs,
verifyMindSpaceMcpScopedToken,
} from './mindspace-mcp-scoped-token.mjs';
const secret = 'mindspace-test-secret-1234';
test('MindSpace MCP token binds user, session, package, workspace, and tools', () => {
const token = mintMindSpaceMcpScopedToken({
secret,
userId: 'user-1',
sessionId: 'session-1',
packageId: 'cp_session-1',
workspaceRef:
'mindspace://users/user-1/workspace',
tools: ['write_file', 'read_file'],
now: 1_000_000,
tokenId: 'token-1',
});
const claims = verifyMindSpaceMcpScopedToken({
token,
secret,
tool: 'write_file',
now: 1_001_000,
});
assert.deepEqual(claims, {
userId: 'user-1',
sessionId: 'session-1',
packageId: 'cp_session-1',
workspaceRef:
'mindspace://users/user-1/workspace',
tools: ['read_file', 'write_file'],
issuedAt: 1_000_000,
expiresAt: 1_900_000,
tokenId: 'token-1',
});
});
test('MindSpace MCP token rejects tampering, expiry, and tools outside the allowlist', () => {
const token = mintMindSpaceMcpScopedToken({
secret,
userId: 'user-1',
sessionId: 'session-1',
packageId: 'cp_session-1',
workspaceRef:
'mindspace://users/user-1/workspace',
tools: ['read_file'],
ttlSeconds: 60,
now: 1_000_000,
tokenId: 'token-1',
});
assert.throws(
() =>
verifyMindSpaceMcpScopedToken({
token: `${token}x`,
secret,
now: 1_001_000,
}),
/signature/,
);
assert.throws(
() =>
verifyMindSpaceMcpScopedToken({
token,
secret,
tool: 'write_file',
now: 1_001_000,
}),
(error) =>
error?.code === 'mcp_tool_forbidden',
);
assert.throws(
() =>
verifyMindSpaceMcpScopedToken({
token,
secret,
now: 2_000_000,
clockSkewSeconds: 0,
}),
(error) =>
error?.code === 'expired_mcp_token',
);
});
test('MindSpace MCP token refuses incomplete scopes and weak secrets', () => {
assert.throws(
() =>
mintMindSpaceMcpScopedToken({
secret: 'short',
userId: 'user-1',
sessionId: 'session-1',
packageId: 'cp_session-1',
workspaceRef:
'mindspace://users/user-1/workspace',
tools: ['read_file'],
}),
(error) =>
error?.code ===
'invalid_mcp_token_secret',
);
assert.throws(
() =>
mintMindSpaceMcpScopedToken({
secret,
userId: 'user-1',
sessionId: 'session-1',
packageId: 'cp_session-1',
workspaceRef:
'mindspace://users/user-1/workspace',
tools: [],
}),
(error) =>
error?.code === 'invalid_mcp_scope',
);
});
test('MindSpace MCP token peek reports expiry and rotation window', () => {
const token = mintMindSpaceMcpScopedToken({
secret,
userId: 'user-1',
sessionId: 'session-1',
packageId: 'cp_session-1',
workspaceRef: 'mindspace://users/user-1/workspace',
tools: ['write_file'],
ttlSeconds: 3600,
now: 1_000_000,
tokenId: 'token-1',
});
assert.equal(peekMindSpaceMcpScopedTokenExpiryMs(token), 4_600_000);
assert.equal(
mindSpaceMcpScopedTokenNeedsRotation(token, { now: 1_000_000, skewSeconds: 120 }),
false,
);
assert.equal(
mindSpaceMcpScopedTokenNeedsRotation(token, {
now: 4_540_000,
skewSeconds: 120,
}),
true,
);
assert.equal(
mindSpaceMcpScopedTokenNeedsRotation('not-a-token', { now: 1_000_000 }),
true,
);
});