@rubytech/create-maxy-code 0.1.410 → 0.1.412
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/account-scope/dist/index.d.ts +27 -0
- package/payload/platform/lib/account-scope/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/account-scope/dist/index.js +33 -0
- package/payload/platform/lib/account-scope/dist/index.js.map +1 -0
- package/payload/platform/lib/account-scope/src/index.ts +43 -0
- package/payload/platform/lib/account-scope/tsconfig.json +5 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +35 -1
- package/payload/platform/plugins/business-assistant/skills/e-sign/SKILL.md +2 -0
- package/payload/platform/plugins/docs/references/cross-account-authority.md +23 -0
- package/payload/platform/plugins/docs/references/memory-guide.md +6 -0
- package/payload/platform/plugins/filesystem/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/filesystem/PLUGIN.md +63 -0
- package/payload/platform/plugins/filesystem/lib/mcp-spawn-tee/index.js +193 -0
- package/payload/platform/plugins/filesystem/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/filesystem/mcp/dist/index.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/index.js +91 -0
- package/payload/platform/plugins/filesystem/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js +89 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/result.d.ts +12 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/result.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/result.js +6 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/result.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +45 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +86 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/walk.d.ts +11 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/walk.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/walk.js +64 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/walk.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js +94 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts +8 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js +40 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts +6 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js +13 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts +7 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js +71 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts +6 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js +26 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts +6 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js +28 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts +7 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js +25 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/package.json +21 -0
- package/payload/platform/plugins/filesystem/mcp/vitest.config.ts +8 -0
- package/payload/platform/plugins/memory/PLUGIN.md +6 -0
- package/payload/platform/plugins/memory/mcp/dist/index-testable.d.ts +34 -0
- package/payload/platform/plugins/memory/mcp/dist/index-testable.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/index-testable.js +60 -0
- package/payload/platform/plugins/memory/mcp/dist/index-testable.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js +275 -133
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.js +65 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.js +54 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/resolve-tool-account.test.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +7 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js +6 -1
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.d.ts +7 -1
- package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.js +7 -2
- package/payload/platform/services/claude-session-manager/dist/claude-keychain-write.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +37 -0
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +34 -1
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/cross-account-census.d.ts +34 -0
- package/payload/platform/services/claude-session-manager/dist/cross-account-census.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/cross-account-census.js +98 -0
- package/payload/platform/services/claude-session-manager/dist/cross-account-census.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +10 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +17 -0
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +25 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +7 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +8 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/server/{chunk-ZYS5V5QG.js → chunk-3Z5WE53X.js} +4 -0
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-D36zz_SY.js → AdminLoginScreens-CYPTMmTk.js} +1 -1
- package/payload/server/public/assets/AdminShell-CZH_EZIy.js +2 -0
- package/payload/server/public/assets/{Checkbox-54KtArF3.js → Checkbox-B0pbYJDQ.js} +1 -1
- package/payload/server/public/assets/{Transcript-BCpiXt4J.js → Transcript-CYaAPBFX.js} +1 -1
- package/payload/server/public/assets/{admin-C0FCHcJj.js → admin-BKDMSRto.js} +1 -1
- package/payload/server/public/assets/{browser-bKeZ5iLx.js → browser-CxeMDDZA.js} +1 -1
- package/payload/server/public/assets/{calendar-BDPBArFA.js → calendar-DiIiTY9-.js} +1 -1
- package/payload/server/public/assets/chat-C56Oqvt1.js +1 -0
- package/payload/server/public/assets/chevron-left-Da-iZGi_.js +1 -0
- package/payload/server/public/assets/data-ZUdT44Ba.js +1 -0
- package/payload/server/public/assets/{graph-Dvru9CW9.js → graph-DC3dwnMZ.js} +1 -1
- package/payload/server/public/assets/{graph-labels-DLhR6Rit.js → graph-labels-Csnovm_c.js} +1 -1
- package/payload/server/public/assets/{maximize-2-CyPKq7HZ.js → maximize-2-WRUJsg5n.js} +1 -1
- package/payload/server/public/assets/{operator-Ql5iQXB-.js → operator-BpzeHTAw.js} +1 -1
- package/payload/server/public/assets/{page-ClJOW2fk.js → page-8jJOxx6y.js} +1 -1
- package/payload/server/public/assets/{page-YsTtZsn6.js → page-IQDLdebG.js} +1 -1
- package/payload/server/public/assets/{public-BlDxwcmS.js → public-Dqg7jwjq.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-DSynJPZX.js → rotate-ccw-BayMWwfc.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CRZfyJXR.css +1 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +5 -5
- package/payload/server/public/chat.html +9 -9
- package/payload/server/public/data.html +8 -8
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +11 -11
- package/payload/server/public/operator.html +11 -11
- package/payload/server/public/public.html +9 -9
- package/payload/server/server.js +26 -19
- package/payload/server/public/assets/AdminShell-DH6Lcj-d.js +0 -1
- package/payload/server/public/assets/chat-Cp_1ebzU.js +0 -1
- package/payload/server/public/assets/chevron-left-S7Nk-se6.js +0 -1
- package/payload/server/public/assets/data-BshlTgIW.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CJelLQK-.css +0 -1
- /package/payload/server/public/assets/{useSubAccountSwitcher-DGKQxXDD.js → useSubAccountSwitcher-C9aLg8yI.js} +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { initStderrTee } from "../../../../lib/mcp-stderr-tee/dist/index.js";
|
|
2
|
+
initStderrTee("filesystem");
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { eagerTool } from "../../../../lib/mcp-eager/dist/index.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
import { readPluginHouseScope } from "./lib/scope.js";
|
|
9
|
+
import { fileRead } from "./tools/file-read.js";
|
|
10
|
+
import { fileWrite } from "./tools/file-write.js";
|
|
11
|
+
import { fileEdit } from "./tools/file-edit.js";
|
|
12
|
+
import { fileList } from "./tools/file-list.js";
|
|
13
|
+
import { fileGlob } from "./tools/file-glob.js";
|
|
14
|
+
import { fileGrep } from "./tools/file-grep.js";
|
|
15
|
+
// Cast to `any` to avoid TS2589 — the same accumulation limit the other
|
|
16
|
+
// plugins hit when registering several typed tool signatures.
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
const server = new McpServer({ name: "maxy-filesystem", version: "0.1.0" });
|
|
19
|
+
// Plugin-system boot tolerance: module-init must never throw; plugin-system
|
|
20
|
+
// spawn enumerates tools/list before ACCOUNT_ID is set. Per-call refusal
|
|
21
|
+
// preserves account isolation.
|
|
22
|
+
const ownAccountId = process.env.ACCOUNT_ID ?? null;
|
|
23
|
+
// Fail-closed read of the boundary — see readPluginHouseScope. Never trusts a
|
|
24
|
+
// literal ${HOUSE_ADMIN_SCOPE} placeholder or an empty value as a real scope.
|
|
25
|
+
const houseScope = readPluginHouseScope(process.env);
|
|
26
|
+
const platformRoot = process.env.PLATFORM_ROOT ?? "";
|
|
27
|
+
process.stderr.write(`[filesystem] boot accountId=${ownAccountId ?? "null"} houseScope=${houseScope ? "set" : "null"}\n`);
|
|
28
|
+
function refuseNoAccount(toolName) {
|
|
29
|
+
process.stderr.write(`[filesystem] tool=${toolName} refuse reason=no-account-context\n`);
|
|
30
|
+
return {
|
|
31
|
+
content: [
|
|
32
|
+
{
|
|
33
|
+
type: "text",
|
|
34
|
+
text: `${toolName} cannot execute: this MCP instance was launched without ACCOUNT_ID/PLATFORM_ROOT (plugin-system metadata-only mode).`,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
isError: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** Build the per-call context once from the spawn env. Null when the metadata-
|
|
41
|
+
* only boot left ACCOUNT_ID/PLATFORM_ROOT unset. `accountsDir` mirrors
|
|
42
|
+
* account.ts's `ACCOUNTS_DIR = resolve(PLATFORM_ROOT, "..", "data/accounts")`. */
|
|
43
|
+
function ctx() {
|
|
44
|
+
if (!ownAccountId || !platformRoot)
|
|
45
|
+
return null;
|
|
46
|
+
return { ownAccountId, houseScope, accountsDir: resolve(platformRoot, "..", "data/accounts") };
|
|
47
|
+
}
|
|
48
|
+
const targetArg = z
|
|
49
|
+
.string()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe("House admin only: a sub-account ID to operate on. Omit to operate on your own account. A non-house session that passes this is denied (cross-account-denied).");
|
|
52
|
+
eagerTool(server, "file-read", "Read a UTF-8 file under the account directory. Pass a path relative to the account root; pass targetAccountId (house admin only) to read a sub-account's file.", { path: z.string().describe("Path relative to the account directory"), targetAccountId: targetArg }, async (a) => {
|
|
53
|
+
const c = ctx();
|
|
54
|
+
return c ? fileRead(a, c) : refuseNoAccount("file-read");
|
|
55
|
+
});
|
|
56
|
+
eagerTool(server, "file-write", "Write (create or overwrite) a UTF-8 file under the account directory, creating parent directories as needed.", {
|
|
57
|
+
path: z.string().describe("Path relative to the account directory"),
|
|
58
|
+
content: z.string().describe("Full file contents to write"),
|
|
59
|
+
targetAccountId: targetArg,
|
|
60
|
+
}, async (a) => {
|
|
61
|
+
const c = ctx();
|
|
62
|
+
return c ? fileWrite(a, c) : refuseNoAccount("file-write");
|
|
63
|
+
});
|
|
64
|
+
eagerTool(server, "file-edit", "Replace a single unique occurrence of oldString with newString in a file under the account directory. Fails if oldString is absent or matches more than once.", {
|
|
65
|
+
path: z.string().describe("Path relative to the account directory"),
|
|
66
|
+
oldString: z.string().describe("Exact text to replace (must occur exactly once)"),
|
|
67
|
+
newString: z.string().describe("Replacement text"),
|
|
68
|
+
targetAccountId: targetArg,
|
|
69
|
+
}, async (a) => {
|
|
70
|
+
const c = ctx();
|
|
71
|
+
return c ? fileEdit(a, c) : refuseNoAccount("file-edit");
|
|
72
|
+
});
|
|
73
|
+
eagerTool(server, "file-list", "List the entries of a directory under the account directory (name + type). Omit path to list the account root.", { path: z.string().optional().describe("Directory relative to the account root"), targetAccountId: targetArg }, async (a) => {
|
|
74
|
+
const c = ctx();
|
|
75
|
+
return c ? fileList(a, c) : refuseNoAccount("file-list");
|
|
76
|
+
});
|
|
77
|
+
eagerTool(server, "file-glob", "List files under the account directory matching a glob (**, *, ?), returned as paths relative to the account root.", { pattern: z.string().describe("Glob pattern, e.g. **/*.md"), targetAccountId: targetArg }, async (a) => {
|
|
78
|
+
const c = ctx();
|
|
79
|
+
return c ? fileGlob(a, c) : refuseNoAccount("file-glob");
|
|
80
|
+
});
|
|
81
|
+
eagerTool(server, "file-grep", "Search file contents under the account directory for a JavaScript regular expression, returning file:line:preview matches. Omit path to search the whole account.", {
|
|
82
|
+
pattern: z.string().describe("JavaScript regular expression"),
|
|
83
|
+
path: z.string().optional().describe("Subdirectory (relative) to limit the search"),
|
|
84
|
+
targetAccountId: targetArg,
|
|
85
|
+
}, async (a) => {
|
|
86
|
+
const c = ctx();
|
|
87
|
+
return c ? fileGrep(a, c) : refuseNoAccount("file-grep");
|
|
88
|
+
});
|
|
89
|
+
const transport = new StdioServerTransport();
|
|
90
|
+
await server.connect(transport);
|
|
91
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.test.d.ts","sourceRoot":"","sources":["../../../src/lib/__tests__/scope.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, symlinkSync, rmSync, realpathSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { resolveRoot, containedPath, readPluginHouseScope } from "../scope.js";
|
|
6
|
+
// enumerateValidAccountIds only counts UUID-named dirs with a parseable
|
|
7
|
+
// account.json, so the fixtures use real UUIDs.
|
|
8
|
+
const HOUSE = "11111111-1111-4111-8111-111111111111";
|
|
9
|
+
const CLIENT = "22222222-2222-4222-8222-222222222222";
|
|
10
|
+
const GHOST = "33333333-3333-4333-8333-333333333333";
|
|
11
|
+
let accountsDir;
|
|
12
|
+
let outsideDir;
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
accountsDir = mkdtempSync(join(tmpdir(), "xacct-accounts-"));
|
|
15
|
+
outsideDir = mkdtempSync(join(tmpdir(), "xacct-outside-"));
|
|
16
|
+
for (const id of [HOUSE, CLIENT]) {
|
|
17
|
+
mkdirSync(join(accountsDir, id), { recursive: true });
|
|
18
|
+
writeFileSync(join(accountsDir, id, "account.json"), JSON.stringify({ accountId: id }));
|
|
19
|
+
}
|
|
20
|
+
writeFileSync(join(outsideDir, "secret.txt"), "secret");
|
|
21
|
+
});
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
rmSync(accountsDir, { recursive: true, force: true });
|
|
24
|
+
rmSync(outsideDir, { recursive: true, force: true });
|
|
25
|
+
});
|
|
26
|
+
const houseCtx = () => ({ ownAccountId: HOUSE, houseScope: HOUSE, accountsDir });
|
|
27
|
+
const clientCtx = () => ({ ownAccountId: CLIENT, houseScope: null, accountsDir });
|
|
28
|
+
describe("resolveRoot — fail-closed gate", () => {
|
|
29
|
+
it("no target → own account root", () => {
|
|
30
|
+
const r = resolveRoot(houseCtx(), undefined, "file-read");
|
|
31
|
+
expect(r).toEqual({ root: resolve(accountsDir, HOUSE), resolved: HOUSE });
|
|
32
|
+
});
|
|
33
|
+
it("house scope + valid target → target root", () => {
|
|
34
|
+
const r = resolveRoot(houseCtx(), CLIENT, "file-read");
|
|
35
|
+
expect(r).toEqual({ root: resolve(accountsDir, CLIENT), resolved: CLIENT });
|
|
36
|
+
});
|
|
37
|
+
it("non-house session + target → cross-account-denied", () => {
|
|
38
|
+
const r = resolveRoot(clientCtx(), HOUSE, "file-read");
|
|
39
|
+
expect(r).toEqual({ reject: "cross-account-denied" });
|
|
40
|
+
});
|
|
41
|
+
it("house scope + unknown target → cross-account-invalid-target", () => {
|
|
42
|
+
const r = resolveRoot(houseCtx(), GHOST, "file-read");
|
|
43
|
+
expect(r).toEqual({ reject: "cross-account-invalid-target" });
|
|
44
|
+
});
|
|
45
|
+
it("house scope + target == own → own root (self allowed)", () => {
|
|
46
|
+
const r = resolveRoot(houseCtx(), HOUSE, "file-read");
|
|
47
|
+
expect(r).toEqual({ root: resolve(accountsDir, HOUSE), resolved: HOUSE });
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe("readPluginHouseScope — fail-closed against loader substitution", () => {
|
|
51
|
+
it("returns the scope when a real value is set", () => {
|
|
52
|
+
expect(readPluginHouseScope({ HOUSE_ADMIN_SCOPE: HOUSE })).toBe(HOUSE);
|
|
53
|
+
});
|
|
54
|
+
it("returns null when absent (non-house session)", () => {
|
|
55
|
+
expect(readPluginHouseScope({})).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
it("returns null when empty", () => {
|
|
58
|
+
expect(readPluginHouseScope({ HOUSE_ADMIN_SCOPE: "" })).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
it("returns null for an unsubstituted ${...} placeholder (the escalation guard)", () => {
|
|
61
|
+
expect(readPluginHouseScope({ HOUSE_ADMIN_SCOPE: "${HOUSE_ADMIN_SCOPE}" })).toBeNull();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe("containedPath — traversal guard", () => {
|
|
65
|
+
it("allows a legitimate file directly under root", () => {
|
|
66
|
+
const root = resolve(accountsDir, HOUSE);
|
|
67
|
+
const realRoot = realpathSync(root); // macOS resolves /var → /private/var
|
|
68
|
+
expect(containedPath(root, "SOUL.md")).toBe(join(realRoot, "SOUL.md"));
|
|
69
|
+
});
|
|
70
|
+
it("allows a nested not-yet-existing (create) path under root", () => {
|
|
71
|
+
const root = resolve(accountsDir, HOUSE);
|
|
72
|
+
const realRoot = realpathSync(root);
|
|
73
|
+
expect(containedPath(root, "agents/x/new.txt")).toBe(join(realRoot, "agents/x/new.txt"));
|
|
74
|
+
});
|
|
75
|
+
it("rejects ../ escape to a sibling account", () => {
|
|
76
|
+
const root = resolve(accountsDir, HOUSE);
|
|
77
|
+
expect(() => containedPath(root, `../${CLIENT}/account.json`)).toThrow("path-escape");
|
|
78
|
+
});
|
|
79
|
+
it("rejects an absolute path outside the account dir", () => {
|
|
80
|
+
const root = resolve(accountsDir, HOUSE);
|
|
81
|
+
expect(() => containedPath(root, "/etc/passwd")).toThrow("path-escape");
|
|
82
|
+
});
|
|
83
|
+
it("rejects a symlink that escapes the account dir", () => {
|
|
84
|
+
const root = resolve(accountsDir, HOUSE);
|
|
85
|
+
symlinkSync(outsideDir, join(root, "escape"));
|
|
86
|
+
expect(() => containedPath(root, "escape/secret.txt")).toThrow("path-escape");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=scope.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/scope.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ToolResult {
|
|
2
|
+
content: {
|
|
3
|
+
type: "text";
|
|
4
|
+
text: string;
|
|
5
|
+
}[];
|
|
6
|
+
/** Present and true only on error results, so `.isError` is well-typed on the
|
|
7
|
+
* ok|err union that handlers return. */
|
|
8
|
+
isError?: true;
|
|
9
|
+
}
|
|
10
|
+
export declare const ok: (text: string) => ToolResult;
|
|
11
|
+
export declare const err: (text: string) => ToolResult;
|
|
12
|
+
//# sourceMappingURL=result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/lib/result.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1C;6CACyC;IACzC,OAAO,CAAC,EAAE,IAAI,CAAC;CAChB;AAED,eAAO,MAAM,EAAE,GAAI,MAAM,MAAM,KAAG,UAAqD,CAAC;AACxF,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,UAGjC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/lib/result.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAY,EAAc,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AACxF,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAc,EAAE,CAAC,CAAC;IAChD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjC,OAAO,EAAE,IAAI;CACd,CAAC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read HOUSE_ADMIN_SCOPE for the plugin, fail-closed. HOUSE_ADMIN_SCOPE is the
|
|
3
|
+
* whole boundary: it is present in the spawn env ONLY for a house role:admin
|
|
4
|
+
* session (Task 1440). This plugin's PLUGIN.md also declares the key with a
|
|
5
|
+
* `${HOUSE_ADMIN_SCOPE}` placeholder so the value flows on loaders that pass
|
|
6
|
+
* only declared env keys — but an UNSET placeholder is substituted
|
|
7
|
+
* differently across spawn loaders: some yield empty, some leave the literal
|
|
8
|
+
* `${HOUSE_ADMIN_SCOPE}` string (which is truthy). Treating a literal
|
|
9
|
+
* placeholder or an empty value as "no scope" makes a non-house session
|
|
10
|
+
* deterministically fail-closed regardless of loader behaviour — the read
|
|
11
|
+
* never trusts a value it did not receive as a real scope. (This is why the
|
|
12
|
+
* plugin does not call the shared `readHouseAdminScope`, whose truthy test
|
|
13
|
+
* would accept the literal placeholder.)
|
|
14
|
+
*/
|
|
15
|
+
export declare function readPluginHouseScope(env: NodeJS.ProcessEnv): string | null;
|
|
16
|
+
export interface Ctx {
|
|
17
|
+
/** The session's own account (spawn env ACCOUNT_ID). */
|
|
18
|
+
ownAccountId: string;
|
|
19
|
+
/** HOUSE_ADMIN_SCOPE from the spawn env; null for any non-house session. */
|
|
20
|
+
houseScope: string | null;
|
|
21
|
+
/** `<install>/data/accounts` — the root that all account dirs live under. */
|
|
22
|
+
accountsDir: string;
|
|
23
|
+
}
|
|
24
|
+
export type ResolveRootResult = {
|
|
25
|
+
root: string;
|
|
26
|
+
resolved: string;
|
|
27
|
+
} | {
|
|
28
|
+
reject: "cross-account-denied" | "cross-account-invalid-target";
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the account directory a tool call acts on, gated fail-closed. Emits
|
|
32
|
+
* the standing [xacct] decision line for every call and op=fs-root on allow.
|
|
33
|
+
* `root` is `<accountsDir>/<resolved>` — the strict filesystem root the caller
|
|
34
|
+
* must contain every path within.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolveRoot(ctx: Ctx, targetAccountId: string | undefined, tool: string): ResolveRootResult;
|
|
37
|
+
/**
|
|
38
|
+
* Resolve `relPath` against the account `root` and prove it stays inside.
|
|
39
|
+
* Lexical containment rejects `../` and absolute-path escapes; a realpath check
|
|
40
|
+
* on the deepest EXISTING ancestor rejects symlink escapes and still permits a
|
|
41
|
+
* not-yet-existing (create) target. Throws Error("path-escape") after emitting
|
|
42
|
+
* op=path-escape-reject; the caller surfaces it as an isError tool result.
|
|
43
|
+
*/
|
|
44
|
+
export declare function containedPath(root: string, relPath: string): string;
|
|
45
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/lib/scope.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CAK1E;AAED,MAAM,WAAW,GAAG;IAClB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,MAAM,EAAE,sBAAsB,GAAG,8BAA8B,CAAA;CAAE,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,GAAG,EACR,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,IAAI,EAAE,MAAM,GACX,iBAAiB,CAqBnB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAenE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// scope.ts — the security core of the `filesystem` plugin.
|
|
2
|
+
//
|
|
3
|
+
// Every file tool routes through here. `resolveRoot` runs the ONE landed
|
|
4
|
+
// fail-closed resolver (account-scope) with a valid-account check over
|
|
5
|
+
// `enumerateValidAccountIds`, emitting the [xacct] per-call decision line and
|
|
6
|
+
// the op=fs-root line BEFORE any fs op. `containedPath` roots every path under
|
|
7
|
+
// the resolved account dir and rejects traversal (../, absolute escape) and
|
|
8
|
+
// symlink escapes, emitting op=path-escape-reject.
|
|
9
|
+
//
|
|
10
|
+
// The fail-closed backbone is structural, not conventional: HOUSE_ADMIN_SCOPE
|
|
11
|
+
// is stamped into the spawn env ONLY for a non-specialist role:admin session on
|
|
12
|
+
// the house account (Task 1440), so a sub-account, specialist, or public
|
|
13
|
+
// session's plugin process carries houseScope=null and any targetAccountId it
|
|
14
|
+
// passes resolves to cross-account-denied.
|
|
15
|
+
import { resolve, dirname, sep } from "node:path";
|
|
16
|
+
import { realpathSync, existsSync } from "node:fs";
|
|
17
|
+
import { resolveEffectiveAccountCore } from "../../../../../lib/account-scope/dist/index.js";
|
|
18
|
+
import { enumerateValidAccountIds } from "../../../../../lib/account-enumeration/dist/index.js";
|
|
19
|
+
const short = (id) => id.slice(0, 8);
|
|
20
|
+
/**
|
|
21
|
+
* Read HOUSE_ADMIN_SCOPE for the plugin, fail-closed. HOUSE_ADMIN_SCOPE is the
|
|
22
|
+
* whole boundary: it is present in the spawn env ONLY for a house role:admin
|
|
23
|
+
* session (Task 1440). This plugin's PLUGIN.md also declares the key with a
|
|
24
|
+
* `${HOUSE_ADMIN_SCOPE}` placeholder so the value flows on loaders that pass
|
|
25
|
+
* only declared env keys — but an UNSET placeholder is substituted
|
|
26
|
+
* differently across spawn loaders: some yield empty, some leave the literal
|
|
27
|
+
* `${HOUSE_ADMIN_SCOPE}` string (which is truthy). Treating a literal
|
|
28
|
+
* placeholder or an empty value as "no scope" makes a non-house session
|
|
29
|
+
* deterministically fail-closed regardless of loader behaviour — the read
|
|
30
|
+
* never trusts a value it did not receive as a real scope. (This is why the
|
|
31
|
+
* plugin does not call the shared `readHouseAdminScope`, whose truthy test
|
|
32
|
+
* would accept the literal placeholder.)
|
|
33
|
+
*/
|
|
34
|
+
export function readPluginHouseScope(env) {
|
|
35
|
+
const raw = env.HOUSE_ADMIN_SCOPE;
|
|
36
|
+
if (!raw)
|
|
37
|
+
return null;
|
|
38
|
+
if (raw.startsWith("${"))
|
|
39
|
+
return null;
|
|
40
|
+
return raw;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Resolve the account directory a tool call acts on, gated fail-closed. Emits
|
|
44
|
+
* the standing [xacct] decision line for every call and op=fs-root on allow.
|
|
45
|
+
* `root` is `<accountsDir>/<resolved>` — the strict filesystem root the caller
|
|
46
|
+
* must contain every path within.
|
|
47
|
+
*/
|
|
48
|
+
export function resolveRoot(ctx, targetAccountId, tool) {
|
|
49
|
+
const isValidAccountId = (id) => enumerateValidAccountIds(ctx.accountsDir).includes(id);
|
|
50
|
+
const eff = resolveEffectiveAccountCore({ ownAccountId: ctx.ownAccountId, houseScope: ctx.houseScope, targetAccountId }, isValidAccountId);
|
|
51
|
+
const targetField = targetAccountId ? short(targetAccountId) : "self";
|
|
52
|
+
const houseField = ctx.houseScope ? "true" : "false";
|
|
53
|
+
if ("reject" in eff) {
|
|
54
|
+
process.stderr.write(`[xacct] op=call tool=${tool} caller=${short(ctx.ownAccountId)} target=${targetField} houseScope=${houseField} decision=deny reason=${eff.reject}\n`);
|
|
55
|
+
return { reject: eff.reject };
|
|
56
|
+
}
|
|
57
|
+
process.stderr.write(`[xacct] op=call tool=${tool} caller=${short(ctx.ownAccountId)} target=${targetField} houseScope=${houseField} decision=allow reason=none\n`);
|
|
58
|
+
const root = resolve(ctx.accountsDir, eff.accountId);
|
|
59
|
+
process.stderr.write(`[xacct] op=fs-root root=data/accounts/${short(eff.accountId)}/\n`);
|
|
60
|
+
return { root, resolved: eff.accountId };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve `relPath` against the account `root` and prove it stays inside.
|
|
64
|
+
* Lexical containment rejects `../` and absolute-path escapes; a realpath check
|
|
65
|
+
* on the deepest EXISTING ancestor rejects symlink escapes and still permits a
|
|
66
|
+
* not-yet-existing (create) target. Throws Error("path-escape") after emitting
|
|
67
|
+
* op=path-escape-reject; the caller surfaces it as an isError tool result.
|
|
68
|
+
*/
|
|
69
|
+
export function containedPath(root, relPath) {
|
|
70
|
+
const realRoot = realpathSync(root);
|
|
71
|
+
const abs = resolve(realRoot, relPath);
|
|
72
|
+
const escape = () => {
|
|
73
|
+
process.stderr.write(`[xacct] op=path-escape-reject path=${relPath} resolved=${short(realRoot.split(sep).pop() ?? "")}\n`);
|
|
74
|
+
throw new Error("path-escape");
|
|
75
|
+
};
|
|
76
|
+
if (abs !== realRoot && !abs.startsWith(realRoot + sep))
|
|
77
|
+
escape();
|
|
78
|
+
let ancestor = abs;
|
|
79
|
+
while (!existsSync(ancestor))
|
|
80
|
+
ancestor = dirname(ancestor);
|
|
81
|
+
const realAncestor = realpathSync(ancestor);
|
|
82
|
+
if (realAncestor !== realRoot && !realAncestor.startsWith(realRoot + sep))
|
|
83
|
+
escape();
|
|
84
|
+
return abs;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/lib/scope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List regular files under `root`, returning paths RELATIVE to root with "/"
|
|
3
|
+
* separators. Symlinked entries are skipped (no escape). Stops at `cap` files.
|
|
4
|
+
*/
|
|
5
|
+
export declare function walkFiles(root: string, cap: number): string[];
|
|
6
|
+
/**
|
|
7
|
+
* Translate a glob (`**`, `*`, `?`) to an anchored RegExp over "/"-joined
|
|
8
|
+
* relative paths. `*` and `?` do not cross "/"; `**` crosses any depth.
|
|
9
|
+
*/
|
|
10
|
+
export declare function globToRegExp(glob: string): RegExp;
|
|
11
|
+
//# sourceMappingURL=walk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../../src/lib/walk.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAoB7D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBjD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Recursive-walk + glob helpers for the glob/grep tools. Both are rooted at an
|
|
2
|
+
// already-resolved account dir and NEVER follow symlinks, so the walk cannot
|
|
3
|
+
// leave the account directory even if a symlink points outside.
|
|
4
|
+
import { readdirSync } from "node:fs";
|
|
5
|
+
import { join, relative, sep } from "node:path";
|
|
6
|
+
/**
|
|
7
|
+
* List regular files under `root`, returning paths RELATIVE to root with "/"
|
|
8
|
+
* separators. Symlinked entries are skipped (no escape). Stops at `cap` files.
|
|
9
|
+
*/
|
|
10
|
+
export function walkFiles(root, cap) {
|
|
11
|
+
const out = [];
|
|
12
|
+
const stack = [root];
|
|
13
|
+
while (stack.length && out.length < cap) {
|
|
14
|
+
const dir = stack.pop();
|
|
15
|
+
let entries;
|
|
16
|
+
try {
|
|
17
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
for (const e of entries) {
|
|
23
|
+
if (out.length >= cap)
|
|
24
|
+
break;
|
|
25
|
+
if (e.isSymbolicLink())
|
|
26
|
+
continue; // never follow a symlink out of root
|
|
27
|
+
const full = join(dir, e.name);
|
|
28
|
+
if (e.isDirectory())
|
|
29
|
+
stack.push(full);
|
|
30
|
+
else if (e.isFile())
|
|
31
|
+
out.push(relative(root, full).split(sep).join("/"));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Translate a glob (`**`, `*`, `?`) to an anchored RegExp over "/"-joined
|
|
38
|
+
* relative paths. `*` and `?` do not cross "/"; `**` crosses any depth.
|
|
39
|
+
*/
|
|
40
|
+
export function globToRegExp(glob) {
|
|
41
|
+
let re = "";
|
|
42
|
+
for (let i = 0; i < glob.length; i++) {
|
|
43
|
+
const c = glob[i];
|
|
44
|
+
if (c === "*") {
|
|
45
|
+
if (glob[i + 1] === "*") {
|
|
46
|
+
re += ".*";
|
|
47
|
+
i++;
|
|
48
|
+
if (glob[i + 1] === "/")
|
|
49
|
+
i++; // absorb the slash after **
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
re += "[^/]*";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (c === "?") {
|
|
56
|
+
re += "[^/]";
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
re += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return new RegExp("^" + re + "$");
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=walk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../../src/lib/walk.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6EAA6E;AAC7E,gEAAgE;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,GAAW;IACjD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAa,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAY,CAAC;QAClC,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG;gBAAE,MAAM;YAC7B,IAAI,CAAC,CAAC,cAAc,EAAE;gBAAE,SAAS,CAAC,qCAAqC;YACvE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;iBACjC,IAAI,CAAC,CAAC,MAAM,EAAE;gBAAE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBACxB,EAAE,IAAI,IAAI,CAAC;gBACX,CAAC,EAAE,CAAC;gBACJ,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG;oBAAE,CAAC,EAAE,CAAC,CAAC,4BAA4B;YAC5D,CAAC;iBAAM,CAAC;gBACN,EAAE,IAAI,OAAO,CAAC;YAChB,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,EAAE,IAAI,MAAM,CAAC;QACf,CAAC;aAAM,CAAC;YACN,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/handlers.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, existsSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { fileRead } from "../file-read.js";
|
|
6
|
+
import { fileWrite } from "../file-write.js";
|
|
7
|
+
import { fileEdit } from "../file-edit.js";
|
|
8
|
+
import { fileList } from "../file-list.js";
|
|
9
|
+
import { fileGlob } from "../file-glob.js";
|
|
10
|
+
import { fileGrep } from "../file-grep.js";
|
|
11
|
+
const HOUSE = "11111111-1111-4111-8111-111111111111";
|
|
12
|
+
const CLIENT = "22222222-2222-4222-8222-222222222222";
|
|
13
|
+
let accountsDir;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
accountsDir = mkdtempSync(join(tmpdir(), "xacct-handlers-"));
|
|
16
|
+
for (const id of [HOUSE, CLIENT]) {
|
|
17
|
+
mkdirSync(join(accountsDir, id), { recursive: true });
|
|
18
|
+
writeFileSync(join(accountsDir, id, "account.json"), JSON.stringify({ accountId: id }));
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
afterEach(() => rmSync(accountsDir, { recursive: true, force: true }));
|
|
22
|
+
const house = () => ({ ownAccountId: HOUSE, houseScope: HOUSE, accountsDir });
|
|
23
|
+
const client = () => ({ ownAccountId: CLIENT, houseScope: null, accountsDir });
|
|
24
|
+
const text = (r) => r.content[0].text;
|
|
25
|
+
describe("file handlers — own account round-trip", () => {
|
|
26
|
+
it("write → read → edit → list on the house's own account", () => {
|
|
27
|
+
expect(fileWrite({ path: "notes/a.txt", content: "hello world" }, house()).isError).toBeUndefined();
|
|
28
|
+
expect(existsSync(join(accountsDir, HOUSE, "notes/a.txt"))).toBe(true);
|
|
29
|
+
expect(text(fileRead({ path: "notes/a.txt" }, house()))).toBe("hello world");
|
|
30
|
+
expect(fileEdit({ path: "notes/a.txt", oldString: "world", newString: "there" }, house()).isError).toBeUndefined();
|
|
31
|
+
expect(readFileSync(join(accountsDir, HOUSE, "notes/a.txt"), "utf-8")).toBe("hello there");
|
|
32
|
+
const listed = text(fileList({ path: "notes" }, house()));
|
|
33
|
+
expect(listed).toContain("a.txt");
|
|
34
|
+
});
|
|
35
|
+
it("file-edit refuses a non-unique oldString", () => {
|
|
36
|
+
fileWrite({ path: "d.txt", content: "x x" }, house());
|
|
37
|
+
const r = fileEdit({ path: "d.txt", oldString: "x", newString: "y" }, house());
|
|
38
|
+
expect(r.isError).toBe(true);
|
|
39
|
+
expect(text(r)).toContain("not unique");
|
|
40
|
+
});
|
|
41
|
+
it("glob and grep find content in the account", () => {
|
|
42
|
+
fileWrite({ path: "docs/readme.md", content: "alpha\nbeta MATCHME gamma" }, house());
|
|
43
|
+
expect(text(fileGlob({ pattern: "**/*.md" }, house()))).toContain("docs/readme.md");
|
|
44
|
+
expect(text(fileGrep({ pattern: "MATCHME" }, house()))).toContain("docs/readme.md:2:");
|
|
45
|
+
});
|
|
46
|
+
it("grep with a path arg reports account-root-relative paths that round-trip", () => {
|
|
47
|
+
fileWrite({ path: "logs/app.log", content: "line1\nMATCHME here" }, house());
|
|
48
|
+
const hit = text(fileGrep({ pattern: "MATCHME", path: "logs" }, house()));
|
|
49
|
+
// root-relative, not subdir-relative — so it feeds straight back into file-read
|
|
50
|
+
expect(hit).toContain("logs/app.log:2:");
|
|
51
|
+
const reported = hit.split(":")[0];
|
|
52
|
+
expect(text(fileRead({ path: reported }, house()))).toContain("MATCHME");
|
|
53
|
+
});
|
|
54
|
+
it("file-edit rejects an empty oldString instead of silently splicing", () => {
|
|
55
|
+
fileWrite({ path: "e.txt", content: "ab" }, house());
|
|
56
|
+
const r = fileEdit({ path: "e.txt", oldString: "", newString: "X" }, house());
|
|
57
|
+
expect(r.isError).toBe(true);
|
|
58
|
+
expect(text(r)).toContain("must not be empty");
|
|
59
|
+
expect(readFileSync(join(accountsDir, HOUSE, "e.txt"), "utf-8")).toBe("ab");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe("file handlers — cross-account gate", () => {
|
|
63
|
+
it("house admin writes into a sub-account by naming targetAccountId", () => {
|
|
64
|
+
const r = fileWrite({ path: "from-house.txt", content: "hi", targetAccountId: CLIENT }, house());
|
|
65
|
+
expect(r.isError).toBeUndefined();
|
|
66
|
+
expect(readFileSync(join(accountsDir, CLIENT, "from-house.txt"), "utf-8")).toBe("hi");
|
|
67
|
+
});
|
|
68
|
+
it("a non-house session naming a target is denied", () => {
|
|
69
|
+
const r = fileRead({ path: "account.json", targetAccountId: HOUSE }, client());
|
|
70
|
+
expect(r.isError).toBe(true);
|
|
71
|
+
expect(text(r)).toContain("cross-account-denied");
|
|
72
|
+
// and it did not read the house file
|
|
73
|
+
expect(text(r)).not.toContain("accountId");
|
|
74
|
+
});
|
|
75
|
+
it("an unknown target is invalid-target", () => {
|
|
76
|
+
const r = fileList({ targetAccountId: "99999999-9999-4999-8999-999999999999" }, house());
|
|
77
|
+
expect(r.isError).toBe(true);
|
|
78
|
+
expect(text(r)).toContain("cross-account-invalid-target");
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("file handlers — traversal guard", () => {
|
|
82
|
+
it("write to a ../ escape is rejected, no file created outside the account", () => {
|
|
83
|
+
const r = fileWrite({ path: `../${CLIENT}/injected.txt`, content: "x" }, house());
|
|
84
|
+
expect(r.isError).toBe(true);
|
|
85
|
+
expect(text(r)).toContain("escapes the account directory");
|
|
86
|
+
expect(existsSync(join(accountsDir, CLIENT, "injected.txt"))).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
it("read of an absolute path outside the account is rejected", () => {
|
|
89
|
+
const r = fileRead({ path: "/etc/hosts" }, house());
|
|
90
|
+
expect(r.isError).toBe(true);
|
|
91
|
+
expect(text(r)).toContain("escapes the account directory");
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=handlers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/handlers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Ctx } from "../lib/scope.js";
|
|
2
|
+
export declare function fileEdit(args: {
|
|
3
|
+
path: string;
|
|
4
|
+
oldString: string;
|
|
5
|
+
newString: string;
|
|
6
|
+
targetAccountId?: string;
|
|
7
|
+
}, ctx: Ctx): import("../lib/result.js").ToolResult;
|
|
8
|
+
//# sourceMappingURL=file-edit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-edit.d.ts","sourceRoot":"","sources":["../../src/tools/file-edit.ts"],"names":[],"mappings":"AACA,OAAO,EAA8B,KAAK,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAGvE,wBAAgB,QAAQ,CACtB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,EACtF,GAAG,EAAE,GAAG,yCA6BT"}
|