mindspace: close authority boundaries
This commit is contained in:
@@ -18,6 +18,9 @@ import {
|
||||
sandboxDeveloperTools,
|
||||
sandboxMcpTools,
|
||||
} from './capabilities.mjs';
|
||||
import {
|
||||
verifyMindSpaceMcpScopedToken,
|
||||
} from './mindspace-mcp-scoped-token.mjs';
|
||||
import { applyPoliciesToCapabilities } from './policies.mjs';
|
||||
|
||||
test('resolveSandboxMcpControlDbEnv rewrites loopback MySQL endpoints for container MCP', () => {
|
||||
@@ -355,6 +358,7 @@ test('sandboxMcpTools returns correct tool list based on capabilities', () => {
|
||||
'write_file',
|
||||
'edit_file',
|
||||
'create_dir',
|
||||
'publish_page',
|
||||
'generate_image',
|
||||
'generate_docx',
|
||||
'generate_long_image',
|
||||
@@ -472,6 +476,105 @@ test('static_publish with sandboxMcp uses stdio sandbox-fs extension instead of
|
||||
assert.ok(!allTools.includes('shell'), 'shell should not be exposed');
|
||||
});
|
||||
|
||||
test('sandboxMcp emits a scoped logical workspace token only for a bound session', () => {
|
||||
const secret =
|
||||
'mindspace-mcp-policy-secret-1234';
|
||||
const caps = {
|
||||
...DEFAULT_USER_CAPABILITIES,
|
||||
static_publish: true,
|
||||
};
|
||||
const sandboxMcp = {
|
||||
serverPath:
|
||||
'/opt/h5/mindspace-sandbox-mcp.mjs',
|
||||
sandboxRoot:
|
||||
'/opt/h5/MindSpace/user-1',
|
||||
workspaceRoot:
|
||||
'/srv/h5/MindSpace/user-1',
|
||||
workspaceRef:
|
||||
'mindspace://users/user-1/workspace',
|
||||
userId: 'user-1',
|
||||
sessionId: 'session-1',
|
||||
packageId: 'cp_session-1',
|
||||
mcpBaseUrl:
|
||||
'http://mindspace.internal:8082/',
|
||||
mcpTokenSecret: secret,
|
||||
};
|
||||
|
||||
const policy =
|
||||
buildAgentExtensionPolicy(caps, {
|
||||
sandboxMcp,
|
||||
});
|
||||
const sandboxExt =
|
||||
policy.extensionOverrides.find(
|
||||
(extension) =>
|
||||
extension.name === 'sandbox-fs',
|
||||
);
|
||||
const claims =
|
||||
verifyMindSpaceMcpScopedToken({
|
||||
token:
|
||||
sandboxExt.envs
|
||||
.MINDSPACE_MCP_SCOPED_TOKEN,
|
||||
secret,
|
||||
tool: 'publish_page',
|
||||
});
|
||||
|
||||
assert.equal(
|
||||
sandboxExt.envs.MINDSPACE_MCP_BASE_URL,
|
||||
'http://mindspace.internal:8082',
|
||||
);
|
||||
assert.equal(
|
||||
sandboxExt.envs.MINDSPACE_SESSION_ID,
|
||||
'session-1',
|
||||
);
|
||||
assert.equal(
|
||||
sandboxExt.envs.MINDSPACE_PACKAGE_ID,
|
||||
'cp_session-1',
|
||||
);
|
||||
assert.equal(claims.userId, 'user-1');
|
||||
assert.equal(
|
||||
claims.workspaceRef,
|
||||
sandboxMcp.workspaceRef,
|
||||
);
|
||||
assert.ok(
|
||||
claims.tools.includes('write_file'),
|
||||
);
|
||||
assert.ok(
|
||||
claims.tools.includes(
|
||||
'generate_long_image',
|
||||
),
|
||||
);
|
||||
assert.ok(
|
||||
claims.tools.includes(
|
||||
'write_binary_file',
|
||||
),
|
||||
);
|
||||
assert.equal(
|
||||
Object.values(sandboxExt.envs).includes(
|
||||
secret,
|
||||
),
|
||||
false,
|
||||
);
|
||||
|
||||
const unboundPolicy =
|
||||
buildAgentExtensionPolicy(caps, {
|
||||
sandboxMcp: {
|
||||
...sandboxMcp,
|
||||
sessionId: null,
|
||||
packageId: null,
|
||||
},
|
||||
});
|
||||
const unboundSandbox =
|
||||
unboundPolicy.extensionOverrides.find(
|
||||
(extension) =>
|
||||
extension.name === 'sandbox-fs',
|
||||
);
|
||||
assert.equal(
|
||||
unboundSandbox.envs
|
||||
.MINDSPACE_MCP_SCOPED_TOKEN,
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
test('sandboxMcp honors container node executable override', () => {
|
||||
const caps = { ...DEFAULT_USER_CAPABILITIES, static_publish: true };
|
||||
const policy = buildAgentExtensionPolicy(caps, {
|
||||
|
||||
Reference in New Issue
Block a user