[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,388 @@
"use strict";
const assert = require("node:assert/strict");
const fs = require("node:fs");
const fsp = require("node:fs/promises");
const os = require("node:os");
const path = require("node:path");
const test = require("node:test");
const { createPluginHostService } = require("./hostService.cjs");
function createOptions(root, configureRpcRegistry) {
return {
app: {
getAppPath: () => process.cwd(),
getPath: () => root,
getVersion: () => "0.0.0",
},
electron: {},
configureRpcRegistry,
};
}
function transportContext() {
return {
signal: new AbortController().signal,
logger: { write: async () => {} },
};
}
test("host RPC registry configuration is complete before runtime initialization", (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const service = createPluginHostService(createOptions(root, (registry) => {
registry.registerRequest("custom.test", () => null);
}));
context.after(() => service.database.close());
const routes = service.rpcRegistry.createRoutes({
pluginId: "com.example.service",
pluginVersion: "1.0.0",
runtimeId: "runtime-1",
runtimeKind: "browser",
});
assert.equal(typeof routes.requestHandlers["custom.test"], "function");
assert.equal(typeof service.terminalProviderService.provide, "function");
});
test("async host RPC registry configuration fails before a service can start", (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
assert.throws(
() => createPluginHostService(createOptions(root, async () => {})),
/must be synchronous/,
);
});
test("host service forwards the transport quota guard to the runtime supervisor", (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
let guarded;
const runtimeMessageGuard = (identity, message) => { guarded = { identity, message }; };
const service = createPluginHostService({
...createOptions(root),
runtimeMessageGuard,
});
context.after(() => service.database.close());
const identity = { runtimeId: "runtime-1" };
const message = { jsonrpc: "2.0" };
service.runtimeSupervisor.runtimeMessageGuard(identity, message);
assert.deepEqual(guarded, { identity, message });
});
test("host service seeds the latest contribution environment before runtime activation", async (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const service = createPluginHostService(createOptions(root));
context.after(() => service.manager.shutdown());
const environment = { locale: "zh-CN", theme: "dark", reducedMotion: true, highContrast: false };
await service.contributionService.setEnvironment(environment);
assert.deepEqual(service.runtimeSupervisor.getInitialEnvironment(), environment);
});
test("runtime cleanup revokes leases before awaiting companion teardown", async (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const service = createPluginHostService(createOptions(root));
context.after(() => service.manager.shutdown());
const events = [];
let releaseCompanions;
service.leaseStore.revokeRuntime = (runtimeId) => {
events.push(`revoke:${runtimeId}`);
};
service.companionSupervisor.releaseRuntime = async (runtimeId) => {
events.push(`release:${runtimeId}`);
await new Promise((resolve) => {
releaseCompanions = resolve;
});
};
let settled = false;
const cleanup = service.runtimeSupervisor.runtimeCleanup({ runtimeId: "runtime-1" })
.finally(() => {
settled = true;
});
await new Promise((resolve) => setImmediate(resolve));
assert.deepEqual(events, ["revoke:runtime-1", "release:runtime-1"]);
assert.equal(settled, false);
releaseCompanions();
await cleanup;
assert.equal(settled, true);
});
test("runtime trust placement precedes required and advanced permission prompts", async (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const events = [];
const service = createPluginHostService({
...createOptions(root),
resolveRuntimeKind: async () => {
events.push("placement");
return "utility";
},
requestPermissionDecision: async (request) => {
events.push(`permission:${request.permission}`);
return { requestId: request.requestId, decision: "allow", scope: "application" };
},
});
context.after(() => service.manager.shutdown());
const manifest = {
manifestVersion: 1,
id: "com.example.advanced",
name: "advanced",
version: "1.0.0",
publisher: "example",
engines: { netcatty: ">=0.0.0", api: ">=0.1.0-internal <0.2.0" },
main: { node: "index.js" },
permissions: { required: ["runtime.advanced", "storage"] },
};
assert.equal(await service.runtimeSupervisor.resolveRuntimeKind({
plugin: { id: manifest.id, activeVersion: manifest.version, manifest },
availableKinds: ["utility"],
securityPrincipal: "verified:test-publisher-key",
signal: new AbortController().signal,
}), "utility");
assert.deepEqual(events, [
"placement",
"permission:storage",
"permission:runtime.advanced",
]);
});
test("first-party placement selects the utility runtime for companion manifests", async (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const requested = [];
const service = createPluginHostService({
...createOptions(root),
requestPermissionDecision: async (request) => {
requested.push(request.permission);
return { requestId: request.requestId, decision: "allow", scope: "application" };
},
});
context.after(() => service.manager.shutdown());
const manifest = {
manifestVersion: 1,
id: "com.example.companion-placement",
name: "companion-placement",
version: "1.0.0",
publisher: "example",
engines: { netcatty: ">=0.0.0", api: ">=0.1.0-internal <0.2.0" },
main: { browser: "browser.js", node: "node.js" },
permissions: {
required: [
"runtime.advanced",
{
permission: "companion.execute",
resources: ["com.example.companion-placement.helper"],
},
],
},
companionExecutables: [{
id: "com.example.companion-placement.helper",
variants: [{
path: "bin/helper",
platforms: [`${process.platform}-${process.arch}`],
sha256: "0".repeat(64),
}],
}],
};
assert.equal(await service.runtimeSupervisor.resolveRuntimeKind({
plugin: { id: manifest.id, activeVersion: manifest.version, manifest },
availableKinds: ["browser", "utility"],
securityPrincipal: "unsigned-package:companion-placement",
signal: new AbortController().signal,
}), "utility");
assert.deepEqual(requested, ["companion.execute", "runtime.advanced"]);
});
test("first-party placement selects utility for dual-entrypoint terminal interceptors", async (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const requested = [];
const service = createPluginHostService({
...createOptions(root),
requestPermissionDecision: async (request) => {
requested.push(request);
return { requestId: request.requestId, decision: "allow", scope: "application" };
},
});
context.after(() => service.manager.shutdown());
const manifest = {
manifestVersion: 1,
id: "com.example.interceptor-placement",
name: "interceptor-placement",
version: "1.0.0",
publisher: "example",
engines: { netcatty: ">=0.0.0", api: ">=0.1.0-internal <0.2.0" },
main: { browser: "browser.js", node: "node.js" },
permissions: {
required: ["runtime.advanced", "provider.terminal", "terminal.intercept.input"],
},
contributes: {
providers: [{
id: "com.example.interceptor-placement.input",
label: "Input filter",
kind: "terminal.interceptor.input",
}],
},
};
assert.equal(await service.runtimeSupervisor.resolveRuntimeKind({
plugin: { id: manifest.id, activeVersion: manifest.version, manifest },
availableKinds: ["browser", "utility"],
securityPrincipal: "unsigned-package:interceptor-placement",
signal: new AbortController().signal,
}), "utility");
assert.deepEqual(requested.map((request) => request.permission), [
"provider.terminal",
"terminal.intercept.input",
"runtime.advanced",
]);
assert.match(
requested.find((request) => request.permission === "terminal.intercept.input")?.reason ?? "",
/arbitrary no-echo input may not be detectable/u,
);
});
test("secure host methods fail closed without an approver while public logging remains available", async (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const service = createPluginHostService(createOptions(root));
context.after(() => service.manager.shutdown());
const routes = service.rpcRegistry.createRoutes({
pluginId: "com.example.service",
pluginVersion: "1.0.0",
runtimeId: "runtime-1",
runtimeKind: "browser",
manifest: {
id: "com.example.service",
name: "service",
publisher: "example",
permissions: { required: ["storage"] },
},
});
await assert.rejects(
routes.requestHandlers["storage.set"]({ key: "answer", value: 42 }, transportContext()),
/not granted/,
);
await routes.notificationHandlers["log.write"]({ level: "info", message: "hello" }, transportContext());
assert.equal(service.database.getValue("com.example.service", "answer"), undefined);
});
test("approved host capabilities reuse application grants through the registry", async (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
let prompts = 0;
const service = createPluginHostService({
...createOptions(root),
requestPermissionDecision: async (request) => {
prompts += 1;
return { requestId: request.requestId, decision: "allow", scope: "application" };
},
});
context.after(() => service.manager.shutdown());
const pluginManifest = {
manifestVersion: 1,
id: "com.example.service",
name: "service",
version: "1.0.0",
publisher: "example",
engines: { netcatty: ">=0.0.0", api: ">=0.1.0-internal <0.2.0" },
main: { browser: "index.js" },
permissions: { required: ["storage"] },
};
service.database.installVersion({
pluginId: pluginManifest.id,
version: pluginManifest.version,
manifest: pluginManifest,
archiveSha256: "a".repeat(64),
packageRelativePath: "com.example.service/1.0.0/package",
});
const routes = service.rpcRegistry.createRoutes({
pluginId: "com.example.service",
pluginVersion: "1.0.0",
runtimeId: "runtime-1",
runtimeKind: "browser",
manifest: pluginManifest,
});
await routes.requestHandlers["storage.set"]({ key: "answer", value: 42 }, transportContext());
assert.deepEqual(
await routes.requestHandlers["storage.get"]({ key: "answer" }, transportContext()),
{ found: true, value: 42 },
);
assert.equal(prompts, 1);
});
test("host service wires a handle-bound directory adapter without changing the RPC seam", async (context) => {
const root = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-")));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const directoryPath = path.join(root, "enumerate");
await fsp.mkdir(directoryPath);
await fsp.writeFile(path.join(directoryPath, "entry.txt"), "entry");
const service = createPluginHostService({
...createOptions(root),
requestPermissionDecision: async (request) => ({
requestId: request.requestId,
decision: "allow",
scope: "once",
}),
openPluginDirectoryHandle: async (directoryPath) => {
const stats = await fsp.stat(directoryPath);
const directory = await fsp.opendir(directoryPath);
return {
stat: async () => stats,
read: () => directory.read(),
close: async () => {
try { await directory.close(); }
catch (error) { if (error?.code !== "ERR_DIR_CLOSED") throw error; }
},
};
},
});
context.after(() => service.manager.shutdown());
const pluginManifest = {
id: "com.example.directory",
name: "directory",
version: "1.0.0",
publisher: "example",
permissions: { optional: [{ permission: "filesystem.read", resources: [directoryPath] }] },
};
const routes = service.rpcRegistry.createRoutes({
pluginId: pluginManifest.id,
pluginVersion: pluginManifest.version,
runtimeId: "runtime-1",
runtimeKind: "browser",
manifest: pluginManifest,
});
assert.deepEqual(
await routes.requestHandlers["filesystem.readDirectory"](
{ path: directoryPath },
transportContext(),
),
{ entries: [{ name: "entry.txt", kind: "file" }] },
);
});
test("custom host methods without an explicit authorization classification are denied", async (context) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-plugin-host-service-"));
context.after(() => fs.rmSync(root, { recursive: true, force: true }));
const service = createPluginHostService(createOptions(root, (registry) => {
registry.registerRequest("custom.unclassified", () => ({ value: true }));
}));
context.after(() => service.manager.shutdown());
const routes = service.rpcRegistry.createRoutes({
pluginId: "com.example.service",
pluginVersion: "1.0.0",
runtimeId: "runtime-1",
runtimeKind: "browser",
manifest: { permissions: { optional: ["settings.read"] } },
});
await assert.rejects(
routes.requestHandlers["custom.unclassified"]({}, transportContext()),
/no authorization policy/,
);
});