Files
NetMesh/electron/plugins/secureCapabilities.test.cjs
zhaolei 3c72efcb7f
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
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

337 lines
12 KiB
JavaScript

"use strict";
const assert = require("node:assert/strict");
const test = require("node:test");
const { registerSecurePluginCapabilities } = require("./secureCapabilities.cjs");
function createRegistrations(secretStore) {
const requests = new Map();
const registry = {
use() {},
registerRequest(method, handler) { requests.set(method, handler); },
};
const middlewareOwner = { createMiddleware: () => async (_context, next) => next() };
const broker = new Proxy({}, { get: () => () => ({}) });
registerSecurePluginCapabilities(registry, {
quotaManager: middlewareOwner,
permissionEngine: middlewareOwner,
secretStore,
credentialBroker: broker,
networkBroker: broker,
filesystemBroker: broker,
companionSupervisor: broker,
assertLeaseParams: (params) => params,
});
return requests;
}
test("secret mutations recheck runtime activity immediately before commit", async () => {
const events = [];
const requests = createRegistrations({
set(_pluginId, _key, _value) {
events.push("set");
return { kind: "secret", id: "secret-reference-0000000000000000", key: "api-key" };
},
delete() { events.push("delete"); },
getReference() { return null; },
});
const activeContext = {
pluginId: "com.example.secure",
async assertActive() { events.push("active"); },
};
await requests.get("secrets.set")({ key: "api-key", value: "value" }, activeContext);
await requests.get("secrets.delete")({ key: "api-key" }, activeContext);
assert.deepEqual(events, ["active", "set", "active", "delete"]);
const stoppedContext = {
pluginId: "com.example.secure",
async assertActive() { throw new Error("runtime stopped"); },
};
await assert.rejects(
requests.get("secrets.set")({ key: "api-key", value: "value" }, stoppedContext),
/runtime stopped/,
);
await assert.rejects(
requests.get("secrets.delete")({ key: "api-key" }, stoppedContext),
/runtime stopped/,
);
assert.deepEqual(events, ["active", "set", "active", "delete"]);
});
test("filesystem RPC authorization fixes resource kind by operation without host I/O", () => {
const registrations = new Map();
const registry = {
use() {},
registerRequest(method, handler, options) { registrations.set(method, { handler, options }); },
};
const middlewareOwner = { createMiddleware: () => async (_context, next) => next() };
const filesystemCalls = [];
const filesystemBroker = {
validateRead: (params) => params,
validateWrite: (params) => params,
validatePath: (params) => params,
describeReadAuthorization(params, resourceKind) {
filesystemCalls.push([params.path, resourceKind]);
return { permission: "filesystem.read", resources: [params.path], resourceKinds: [resourceKind] };
},
describeWriteAuthorization(params) {
filesystemCalls.push([params.path, "exact"]);
return { permission: "filesystem.write", resources: [params.path], resourceKinds: ["exact"] };
},
readFile: async () => null,
stat: async () => null,
readDirectory: async () => null,
writeFile: async () => null,
};
const broker = new Proxy({}, { get: () => () => ({}) });
registerSecurePluginCapabilities(registry, {
quotaManager: middlewareOwner,
permissionEngine: middlewareOwner,
secretStore: {},
credentialBroker: broker,
networkBroker: broker,
filesystemBroker,
companionSupervisor: broker,
assertLeaseParams: (params) => params,
});
const target = "/canonical/target";
for (const method of ["filesystem.readFile", "filesystem.stat", "filesystem.readDirectory"]) {
registrations.get(method).options.authorization({ path: target });
}
registrations.get("filesystem.writeFile").options.authorization({
path: target,
data: "value",
overwrite: true,
});
assert.deepEqual(filesystemCalls, [
[target, "exact"],
[target, "exact"],
[target, "directory"],
[target, "exact"],
]);
});
test("companion start authorization receives host-owned runtime placement", () => {
const registrations = new Map();
const registry = {
use() {},
registerRequest(method, handler, options) { registrations.set(method, { handler, options }); },
};
const middlewareOwner = { createMiddleware: () => async (_context, next) => next() };
const broker = new Proxy({}, { get: () => () => ({}) });
let observedContext;
const companionSupervisor = {
validateStart: (params) => params,
describeStartAuthorization(params, context) {
observedContext = context;
return {
permission: "companion.execute",
resources: [params.companionId],
};
},
validateRequest: (params) => params,
validateStop: (params) => params,
describeHandleAuthorization: () => ({
permission: "companion.execute",
resources: ["com.example.secure.helper"],
}),
start: async () => null,
request: async () => null,
stop: async () => null,
};
registerSecurePluginCapabilities(registry, {
quotaManager: middlewareOwner,
permissionEngine: middlewareOwner,
secretStore: {},
credentialBroker: broker,
networkBroker: broker,
filesystemBroker: broker,
companionSupervisor,
assertLeaseParams: (params) => params,
});
const runtimeContext = { runtimeKind: "utility", runtimeId: "runtime-advanced" };
registrations.get("companion.start").options.authorization({
companionId: "com.example.secure.helper",
}, runtimeContext);
assert.equal(observedContext, runtimeContext);
});
test("companion requests consume operation-bound credential leases exactly once", async () => {
const registrations = new Map();
const registry = {
use() {},
registerRequest(method, handler, options) { registrations.set(method, { handler, options }); },
};
const middlewareOwner = { createMiddleware: () => async (_context, next) => next() };
const consumed = [];
const forwarded = [];
const credentialBroker = {
async consumeLease(context, lease, operationId) {
consumed.push({ context, lease, operationId });
return lease.id.endsWith("user") ? "alice" : "correct horse battery staple";
},
};
const companionSupervisor = {
validateRequest(params) { return params; },
describeHandleAuthorization: () => ({
permission: "companion.execute",
resources: ["com.example.secure.helper"],
}),
async request(params, context) {
forwarded.push({ params, context });
return { accepted: true };
},
validateStart: (params) => params,
validateStop: (params) => params,
describeStartAuthorization: () => ({
permission: "companion.execute",
resources: ["com.example.secure.helper"],
}),
start: async () => null,
stop: async () => null,
};
const broker = new Proxy({}, { get: () => () => ({}) });
registerSecurePluginCapabilities(registry, {
quotaManager: middlewareOwner,
permissionEngine: middlewareOwner,
secretStore: {},
credentialBroker,
networkBroker: broker,
filesystemBroker: broker,
companionSupervisor,
assertLeaseParams: (params) => params,
});
const context = {
pluginId: "com.example.secure",
async assertActive() {},
};
const result = await registrations.get("companion.request").handler({
handleId: "companion-handle-0001",
method: "authenticate",
params: { host: "example.test" },
credentialLeases: {
username: { kind: "secret-lease", id: "credential-lease-user" },
password: { kind: "secret-lease", id: "credential-lease-password" },
},
operationId: "login",
timeoutMs: 5_000,
}, context);
assert.deepEqual(result, { accepted: true });
assert.equal(consumed.length, 2);
assert.deepEqual(consumed.map(({ lease, operationId }) => [lease.id, operationId]), [
["credential-lease-user", "login"],
["credential-lease-password", "login"],
]);
assert.equal(forwarded.length, 1);
assert.deepEqual(forwarded[0].params, {
handleId: "companion-handle-0001",
method: "authenticate",
params: {
payload: { host: "example.test" },
credentials: {
username: "alice",
password: "correct horse battery staple",
},
},
timeoutMs: 5_000,
});
assert.equal(forwarded[0].context, context);
});
test("network.request injects Authorization from a consumed credential lease", async () => {
const registrations = new Map();
const registry = {
use() {},
registerRequest(method, handler, options) { registrations.set(method, { handler, options }); },
};
const middlewareOwner = { createMiddleware: () => async (_context, next) => next() };
const forwarded = [];
const consumed = [];
const credentialBroker = {
async consumeLease(context, lease, operationId) {
consumed.push({ lease, operationId, pluginId: context.pluginId });
return "lease-token-value";
},
};
const networkBroker = {
// Mirror production validate: preserve credentialLease / authorization.
validate: (params) => ({
url: params.url,
method: params.method ?? "GET",
headers: params.headers ?? {},
timeoutMs: params.timeoutMs ?? 30_000,
...(params.credentialLease === undefined ? {} : { credentialLease: params.credentialLease }),
...(params.authorization === undefined ? {} : { authorization: params.authorization }),
}),
describeAuthorization: () => ({
permission: "network",
resources: ["https://example.com"],
reason: "test",
operationId: "network:https://example.com",
}),
async request(params, context) {
forwarded.push({ params, context });
return { status: 204, headers: {}, body: { encoding: "base64", data: "" } };
},
};
const broker = new Proxy({}, { get: () => () => ({}) });
registerSecurePluginCapabilities(registry, {
quotaManager: middlewareOwner,
permissionEngine: middlewareOwner,
secretStore: {},
credentialBroker,
networkBroker,
filesystemBroker: broker,
companionSupervisor: broker,
assertLeaseParams: (params) => params,
});
const context = {
pluginId: "com.example.secure",
async assertActive() {},
};
const registration = registrations.get("network.request");
// Simulate hostRpcRegistry: validateParams first, then handler(validatedParams).
const validated = registration.options.validateParams({
url: "https://example.com/vault",
credentialLease: {
kind: "secret-lease",
id: "lease-1",
operationId: "network:https://example.com",
expiresAt: Date.now() + 60_000,
},
authorization: { scheme: "Bearer" },
});
await registration.handler(validated, context);
assert.equal(consumed.length, 1);
assert.equal(consumed[0].operationId, "network:https://example.com");
assert.equal(forwarded[0].params.headers.authorization, "Bearer lease-token-value");
assert.equal(forwarded[0].params.credentialLease, undefined);
});
test("networkBroker.validate preserves credentialLease for registry dispatch", () => {
const { PluginNetworkBroker } = require("./networkBroker.cjs");
const broker = new PluginNetworkBroker({
fetch: async () => ({ status: 204, headers: new Headers(), body: null, url: "https://example.com/" }),
permissionEngine: { check: () => {} },
});
const validated = broker.validate({
url: "https://example.com/vault",
credentialLease: {
kind: "secret-lease",
id: "lease-1",
operationId: "network:https://example.com",
expiresAt: Date.now() + 60_000,
},
authorization: { scheme: "Basic", username: "alice" },
});
assert.equal(validated.credentialLease.kind, "secret-lease");
assert.equal(validated.authorization.scheme, "Basic");
assert.equal(validated.authorization.username, "alice");
});