Files
2026-07-13 13:39:12 +08:00

89 lines
3.6 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { evaluateToolScopes } from "../../open-sse/mcp-server/scopeEnforcement.ts";
test("obsidian tools — enforcement disabled allows any", () => {
const result = evaluateToolScopes("obsidian_search_simple", [], false);
assert.equal(result.allowed, true);
});
test("obsidian tools — getClient helper works when token is set", async () => {
// Mock getObsidianToken + getObsidianBaseUrl via dynamic import
const { getObsidianToken, getObsidianBaseUrl } = await import("../../src/lib/db/obsidian.ts");
// These return null/default in test env — just verify they don't throw
assert.equal(typeof getObsidianToken, "function");
assert.equal(typeof getObsidianBaseUrl, "function");
});
test("obsidian tools — missing read:obsidian denied via inline scopes", () => {
const result = evaluateToolScopes("obsidian_search_simple", ["read:health"], true, ["read:obsidian"]);
assert.equal(result.allowed, false);
assert.ok(result.missing.includes("read:obsidian"));
});
test("obsidian tools — correct read scope allowed via inline scopes", () => {
const result = evaluateToolScopes("obsidian_search_simple", ["read:obsidian"], true, ["read:obsidian"]);
assert.equal(result.allowed, true);
assert.deepEqual(result.missing, []);
});
test("obsidian tools — wildcard read:* covers read:obsidian", () => {
const result = evaluateToolScopes("obsidian_search_simple", ["read:*"], true, ["read:obsidian"]);
assert.equal(result.allowed, true);
});
test("obsidian tools — write:obsidian denied for read-only caller", () => {
const result = evaluateToolScopes("obsidian_write_note", ["read:obsidian"], true, ["write:obsidian"]);
assert.equal(result.allowed, false);
assert.ok(result.missing.includes("write:obsidian"));
});
test("obsidian tools — write:obsidian allowed with correct scope", () => {
const result = evaluateToolScopes("obsidian_write_note", ["write:obsidian"], true, ["write:obsidian"]);
assert.equal(result.allowed, true);
});
test("obsidian tools — tool without inline scopes returns denied with tool_definition_missing", () => {
const result = evaluateToolScopes("obsidian_search_simple", ["read:obsidian"], true);
assert.equal(result.allowed, false);
assert.equal(result.reason, "tool_definition_missing");
});
test("obsidian tools — all 10 read tools accept read:obsidian", () => {
const readTools = [
"obsidian_check_status",
"obsidian_search_simple",
"obsidian_search_structured",
"obsidian_read_note",
"obsidian_list_vault",
"obsidian_get_document_map",
"obsidian_get_note_metadata",
"obsidian_get_active_file",
"obsidian_get_periodic_note",
"obsidian_get_tags",
];
for (const name of readTools) {
const result = evaluateToolScopes(name, ["read:obsidian"], true, ["read:obsidian"]);
assert.equal(result.allowed, true, `${name} should be allowed with read:obsidian`);
}
});
test("obsidian tools — all 7 write tools require write:obsidian", () => {
const writeTools = [
"obsidian_write_note",
"obsidian_append_note",
"obsidian_patch_note",
"obsidian_delete_note",
"obsidian_move_note",
"obsidian_execute_command",
"obsidian_open_file",
];
for (const name of writeTools) {
const result = evaluateToolScopes(name, ["read:obsidian"], true, ["write:obsidian"]);
assert.equal(result.allowed, false, `${name} should deny read-only caller`);
const allowed = evaluateToolScopes(name, ["write:obsidian"], true, ["write:obsidian"]);
assert.equal(allowed.allowed, true, `${name} should be allowed with write:obsidian`);
}
});