Files
pikasTech-HWLAB/internal/cloud/json-rpc.test.mjs
T
2026-05-25 03:16:55 +00:00

296 lines
11 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { AUDIT_FIELD_NAMES } from "../audit/index.mjs";
import { ERROR_CODES, validateResponse } from "../protocol/index.mjs";
import { createCloudRuntimeStore } from "../db/runtime-store.mjs";
import { handleJsonRpcRequest } from "./json-rpc.mjs";
test("unknown JSON-RPC method returns an error envelope with audit fields", async () => {
const response = await handleJsonRpcRequest({
jsonrpc: "2.0",
id: "req_01J00000000000000000000000",
method: "hardware.operation.cancel",
params: {
operationId: "op_01J00000000000000000000000"
},
meta: {
traceId: "trc_01J00000000000000000000000",
actorId: "usr_01J00000000000000000000000",
serviceId: "hwlab-cloud-web",
environment: "dev"
}
});
validateResponse(response);
assert.equal(response.error.code, ERROR_CODES.methodNotFound);
assert.equal(Object.hasOwn(response, "result"), false);
const audit = response.error.data.audit;
for (const field of AUDIT_FIELD_NAMES) {
assert.ok(Object.hasOwn(audit, field), `expected audit.${field}`);
}
assert.equal(audit.requestId, "req_01J00000000000000000000000");
assert.equal(audit.actor.id, "usr_01J00000000000000000000000");
assert.equal(audit.operation, "hardware.operation.cancel");
assert.equal(audit.target.type, "rpc_method");
assert.equal(audit.result, "rejected");
});
test("system.health includes the redacted DEV DB env contract", async () => {
const originalUrl = process.env.HWLAB_CLOUD_DB_URL;
const originalSslMode = process.env.HWLAB_CLOUD_DB_SSL_MODE;
delete process.env.HWLAB_CLOUD_DB_URL;
delete process.env.HWLAB_CLOUD_DB_SSL_MODE;
try {
const response = await handleJsonRpcRequest({
jsonrpc: "2.0",
id: "req_01J00000000000000000000002",
method: "system.health",
params: {},
meta: {
traceId: "trc_01J00000000000000000000002",
serviceId: "hwlab-cloud-web",
environment: "dev"
}
});
validateResponse(response);
assert.equal(response.result.status, "degraded");
assert.equal(response.result.db.status, "blocked");
assert.equal(response.result.db.connected, false);
assert.equal(response.result.db.liveConnected, false);
assert.equal(response.result.db.liveDbEvidence, false);
assert.equal(response.result.db.connectionAttempted, false);
assert.equal(response.result.db.connectionResult, "not_attempted_missing_env");
assert.equal(response.result.db.endpointSource, "secret-url-host");
assert.equal(response.result.db.optionalPublicDnsAlias.source, "optional-public-dns-alias");
assert.equal(response.result.db.optionalPublicDnsAlias.requiredForReadiness, false);
assert.equal(response.result.db.optionalPublicDnsAlias.usedForProbe, false);
assert.equal(response.result.db.redaction.valuesRedacted, true);
assert.equal(response.result.db.redaction.secretMaterialRead, false);
assert.equal(response.result.db.safety.liveDbEvidence, false);
assert.equal(response.result.runtime.durable, false);
assert.equal(response.result.runtime.durabilityContract.dbLiveEvidenceIsDurabilityEvidence, false);
assert.equal(response.result.readiness.contractVersion, "v3");
assert.equal(response.result.readiness.durability.status, "blocked");
assert.equal(response.result.readiness.durability.dbLiveEvidenceObserved, false);
assert.equal(response.result.readiness.durability.dbLiveEvidenceIsDurabilityEvidence, false);
assert.equal(response.result.readiness.durability.blockedLayer, "adapter");
assert.ok(response.result.db.missingEnv.includes("HWLAB_CLOUD_DB_URL"));
assert.equal(response.result.db.secretRefs[0].secretName, "hwlab-cloud-api-dev-db");
assert.equal(response.result.db.secretRefs[0].secretKey, "database-url");
assert.equal(response.result.db.secretRefs[0].redacted, true);
} finally {
if (originalUrl === undefined) {
delete process.env.HWLAB_CLOUD_DB_URL;
} else {
process.env.HWLAB_CLOUD_DB_URL = originalUrl;
}
if (originalSslMode === undefined) {
delete process.env.HWLAB_CLOUD_DB_SSL_MODE;
} else {
process.env.HWLAB_CLOUD_DB_SSL_MODE = originalSslMode;
}
}
});
test("JSON-RPC invalid meta reports unknown serviceId reason without leaking secret material", async () => {
const response = await handleJsonRpcRequest({
jsonrpc: "2.0",
id: "req_01J00000000000000000000003",
method: "hardware.invoke.shell",
params: {
projectId: "prj_mvp_topology",
operationId: "op_gateway_timeout_requested",
gatewaySessionId: "gws_DESKTOP-1MHOD9I",
resourceId: "res_windows_host",
capabilityId: "cap_windows_cmd_exec",
input: {
command: "cmd /c echo should-not-dispatch"
}
},
meta: {
traceId: "trc_01J00000000000000000000003",
actorId: "usr_01J00000000000000000000003",
serviceId: "hwlab-code-agent-hotfix",
environment: "dev"
}
});
validateResponse(response);
assert.equal(response.error.code, ERROR_CODES.invalidRequest);
assert.equal(response.error.message, "Invalid JSON-RPC request");
assert.match(response.error.data.reason, /unknown serviceId "hwlab-code-agent-hotfix"/u);
assert.equal(JSON.stringify(response).includes("should-not-dispatch"), false);
assert.equal(JSON.stringify(response).includes("sk-"), false);
});
test("hardware.invoke.shell dispatch timeout honors requested gateway shell timeout with grace", async () => {
let observedTimeoutMs = null;
const response = await handleJsonRpcRequest({
jsonrpc: "2.0",
id: "req_01J00000000000000000000004",
method: "hardware.invoke.shell",
params: {
projectId: "prj_mvp_topology",
gatewaySessionId: "gws_DESKTOP-1MHOD9I",
resourceId: "res_windows_host",
capabilityId: "cap_windows_cmd_exec",
input: {
command: "powershell -NoProfile -Command Start-Sleep -Seconds 45",
timeoutMs: 180000
}
},
meta: {
traceId: "trc_01J00000000000000000000004",
actorId: "usr_01J00000000000000000000004",
serviceId: "hwlab-cloud-web",
environment: "dev"
}
}, {
env: {
HWLAB_GATEWAY_DISPATCH_TIMEOUT_MS: "30000",
HWLAB_GATEWAY_DISPATCH_TIMEOUT_GRACE_MS: "5000"
},
gatewayRegistry: {
isOnline: (gatewaySessionId) => gatewaySessionId === "gws_DESKTOP-1MHOD9I",
enqueue: async ({ timeoutMs }) => {
observedTimeoutMs = timeoutMs;
return {
ok: false,
status: "timed_out",
error: "forced timeout"
};
}
}
});
validateResponse(response);
assert.equal(observedTimeoutMs, 185000);
assert.equal(response.result.status, "timed_out");
assert.equal(response.result.operationId, "op_gateway_timeout_requested");
assert.equal(response.result.dispatch.dispatchStatus, "timed_out");
assert.equal(response.result.dispatch.shellExecuted, false);
});
test("cloud-api runtime accepts register/report/invoke and exposes audit/evidence records", async () => {
const runtimeStore = createCloudRuntimeStore({
now: () => "2026-05-21T00:00:00.000Z"
});
const context = { runtimeStore };
const meta = {
traceId: "trc_01J00000000000000000000010",
actorId: "usr_01J00000000000000000000010",
serviceId: "hwlab-cloud-web",
environment: "dev"
};
async function rpc(id, method, params = {}) {
const response = await handleJsonRpcRequest(
{
jsonrpc: "2.0",
id,
method,
params,
meta
},
context
);
validateResponse(response);
assert.equal(Object.hasOwn(response, "error"), false, response.error?.message);
return response.result;
}
const gateway = await rpc("req_01J00000000000000000000010", "gateway.session.register", {
projectId: "prj_01J00000000000000000000010",
gatewaySessionId: "gws_01J00000000000000000000010",
gatewayId: "gtw_01J00000000000000000000010",
serviceId: "hwlab-gateway-simu",
endpoint: "http://127.0.0.1:7101"
});
assert.equal(gateway.registered, true);
assert.equal(gateway.gatewaySession.status, "connected");
assert.equal(gateway.auditEvent.action, "gateway.session.register");
const resource = await rpc("req_01J00000000000000000000011", "box.resource.register", {
projectId: "prj_01J00000000000000000000010",
gatewaySessionId: "gws_01J00000000000000000000010",
resourceId: "res_01J00000000000000000000010",
boxId: "box_01J00000000000000000000010",
resourceType: "board",
state: "available"
});
assert.equal(resource.registered, true);
assert.equal(resource.resource.environment, "dev");
const capability = await rpc("req_01J00000000000000000000012", "box.capability.report", {
capabilityId: "cap_01J00000000000000000000010",
resourceId: "res_01J00000000000000000000010",
projectId: "prj_01J00000000000000000000010",
name: "shell.exec",
direction: "bidirectional",
valueType: "object",
mutatesState: true
});
assert.equal(capability.reported, true);
assert.equal(capability.capabilities[0].name, "shell.exec");
const invoke = await rpc("req_01J00000000000000000000013", "hardware.invoke.shell", {
projectId: "prj_01J00000000000000000000010",
gatewaySessionId: "gws_01J00000000000000000000010",
resourceId: "res_01J00000000000000000000010",
capabilityId: "cap_01J00000000000000000000010",
input: {
command: "echo hwlab"
}
});
assert.equal(invoke.accepted, true);
assert.equal(invoke.operation.status, "accepted");
assert.equal(invoke.dispatch.shellExecuted, false);
assert.equal(invoke.dispatch.dispatchStatus, "not_connected");
assert.equal(invoke.auditEvent.action, "hardware.invoke.shell");
assert.equal(invoke.evidenceRecord.kind, "trace");
assert.match(invoke.evidenceRecord.sha256, /^[a-f0-9]{64}$/);
const audit = await rpc("req_01J00000000000000000000014", "audit.event.query", {
projectId: "prj_01J00000000000000000000010"
});
assert.equal(audit.count, 5);
assert.ok(audit.events.some((event) => event.action === "hardware.operation.request"));
assert.ok(audit.events.some((event) => event.action === "hardware.invoke.shell"));
const evidence = await rpc("req_01J00000000000000000000015", "evidence.record.query", {
projectId: "prj_01J00000000000000000000010"
});
assert.equal(evidence.count, 1);
assert.equal(evidence.records[0].operationId, invoke.operationId);
assert.equal(evidence.records[0].serviceId, "hwlab-cloud-api");
});
test("hardware.operation.request rejects missing registration instead of faking dispatch", async () => {
const response = await handleJsonRpcRequest({
jsonrpc: "2.0",
id: "req_01J00000000000000000000020",
method: "hardware.operation.request",
params: {
projectId: "prj_01J00000000000000000000020",
gatewaySessionId: "gws_01J00000000000000000000020",
resourceId: "res_01J00000000000000000000020",
capabilityId: "cap_01J00000000000000000000020"
},
meta: {
traceId: "trc_01J00000000000000000000020",
actorId: "usr_01J00000000000000000000020",
serviceId: "hwlab-cloud-web",
environment: "dev"
}
});
validateResponse(response);
assert.equal(response.error.code, ERROR_CODES.sessionNotFound);
assert.equal(response.error.data.audit.operation, "hardware.operation.request");
assert.equal(response.error.data.audit.result, "rejected");
});