feat(controller): observe the bounded Linux execution substrate
This commit is contained in:
parent
098a29e417
commit
3fb33ad841
6 changed files with 341 additions and 2 deletions
|
|
@ -11,6 +11,9 @@ WorkingDirectory=__RELEASE_ROOT__/server-tools/bingshuo-tcs-controller
|
|||
EnvironmentFile=/etc/guanghu/persona-secrets/shared-deepseek.env
|
||||
Environment=BS_TCS_CONTROLLER_STATE_ROOT=/var/lib/guanghu/personas/bingshuo-tcs
|
||||
Environment=BS_TCS_CONTROLLER_PORT=3930
|
||||
Environment=GUANGHU_EXECUTION_BRIDGE_BIN=/opt/guanghu/execution-bridge/current/guanghu-execution-bridge
|
||||
Environment=GUANGHU_EXECUTION_BRIDGE_POLICY=/opt/guanghu/execution-bridge/current/policy.json
|
||||
Environment=GUANGHU_EXECUTION_OBSERVE_INTERVAL_MS=30000
|
||||
ExecStart=/usr/bin/node __RELEASE_ROOT__/server-tools/bingshuo-tcs-controller/server.mjs
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
|
@ -18,7 +21,7 @@ NoNewPrivileges=true
|
|||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadOnlyPaths=__RELEASE_ROOT__ /etc/guanghu/persona-secrets/shared-deepseek.env
|
||||
ReadOnlyPaths=__RELEASE_ROOT__ /etc/guanghu/persona-secrets/shared-deepseek.env /opt/guanghu/execution-bridge
|
||||
ReadWritePaths=/var/lib/guanghu/personas/bingshuo-tcs
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
LockPersonality=true
|
||||
|
|
|
|||
127
server-tools/bingshuo-tcs-controller/execution-observer.mjs
Normal file
127
server-tools/bingshuo-tcs-controller/execution-observer.mjs
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import { execFile as execFileCallback } from "node:child_process";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
const execFile = promisify(execFileCallback);
|
||||
|
||||
export const REQUIRED_PROTOCOL_CHAIN = Object.freeze([
|
||||
"GLS-0301",
|
||||
"GLS-0302",
|
||||
"GLS-0303",
|
||||
"GLS-0306",
|
||||
"GLS-0309",
|
||||
"GLS-0311",
|
||||
"GLS-0130",
|
||||
"GLS-0131",
|
||||
"GLS-0709",
|
||||
"GLS-0710",
|
||||
]);
|
||||
|
||||
const DEFAULT_SERVICES = Object.freeze([
|
||||
"guanghu-ai-discovery.service",
|
||||
"bingshuo-tcs-living-controller.service",
|
||||
"lake-lamp-authz.service",
|
||||
]);
|
||||
|
||||
function safeId(value) {
|
||||
return value.replace(/[^A-Za-z0-9_-]/g, "_");
|
||||
}
|
||||
|
||||
function validateReceipt(receipt, service, targetNodeId) {
|
||||
if (
|
||||
receipt?.schema !== "guanghu.execution-receipt/v1" ||
|
||||
receipt?.target_node_id !== targetNodeId ||
|
||||
receipt?.action?.kind !== "service_status" ||
|
||||
receipt?.action?.resource !== service ||
|
||||
receipt?.adapter !== "LINUX_SYSTEMD_V1"
|
||||
) {
|
||||
throw new Error(`execution_receipt_contract_mismatch:${service}`);
|
||||
}
|
||||
return receipt;
|
||||
}
|
||||
|
||||
export class ExecutionObserver {
|
||||
constructor({
|
||||
binaryPath,
|
||||
policyPath,
|
||||
stateRoot,
|
||||
execute = execFile,
|
||||
targetNodeId = "JD-FD-PRIMARY",
|
||||
subjectId = "ICE-P-ZY001",
|
||||
services = DEFAULT_SERVICES,
|
||||
}) {
|
||||
this.binaryPath = binaryPath;
|
||||
this.policyPath = policyPath;
|
||||
this.stateRoot = stateRoot;
|
||||
this.execute = execute;
|
||||
this.targetNodeId = targetNodeId;
|
||||
this.subjectId = subjectId;
|
||||
this.services = [...services];
|
||||
}
|
||||
|
||||
async observe() {
|
||||
const observedAt = new Date().toISOString();
|
||||
const requestRoot = path.join(this.stateRoot, "execution-observer");
|
||||
await fs.mkdir(requestRoot, { recursive: true, mode: 0o700 });
|
||||
|
||||
const serviceReceipts = [];
|
||||
for (const service of this.services) {
|
||||
const requestId = `JD-COGNITIVE-OBSERVE-${safeId(service)}`;
|
||||
const requestPath = path.join(requestRoot, `${requestId}.json`);
|
||||
const request = {
|
||||
schema: "guanghu.execution-request/v1",
|
||||
request_id: requestId,
|
||||
subject_id: this.subjectId,
|
||||
target_node_id: this.targetNodeId,
|
||||
protocol_chain: REQUIRED_PROTOCOL_CHAIN,
|
||||
action: {
|
||||
kind: "service_status",
|
||||
resource: service,
|
||||
},
|
||||
authorization: null,
|
||||
rollback: null,
|
||||
};
|
||||
await fs.writeFile(
|
||||
requestPath,
|
||||
`${JSON.stringify(request, null, 2)}\n`,
|
||||
{ mode: 0o600 },
|
||||
);
|
||||
const { stdout } = await this.execute(
|
||||
this.binaryPath,
|
||||
["execute", requestPath, this.policyPath],
|
||||
{
|
||||
timeout: 5_000,
|
||||
maxBuffer: 64 * 1024,
|
||||
windowsHide: true,
|
||||
},
|
||||
);
|
||||
serviceReceipts.push(
|
||||
validateReceipt(JSON.parse(stdout), service, this.targetNodeId),
|
||||
);
|
||||
}
|
||||
|
||||
const ready = serviceReceipts.every(
|
||||
(receipt) =>
|
||||
receipt.accepted === true &&
|
||||
receipt.target_state_verified === true &&
|
||||
receipt.final_state === "PASS_100",
|
||||
);
|
||||
return {
|
||||
schema: "guanghu.cognitive-execution-observation/v1",
|
||||
target_node_id: this.targetNodeId,
|
||||
subject_id: this.subjectId,
|
||||
observed_at: observedAt,
|
||||
mode: "READ_ONLY_STATUS",
|
||||
language_authority: "REPO-012",
|
||||
execution_implementation: "REPO-014",
|
||||
linux_role: "COOPERATIVE_EXECUTION_SUBSTRATE",
|
||||
arbitrary_shell: false,
|
||||
restart_allowed: false,
|
||||
bridge_bound: 100,
|
||||
target_state_verified: ready ? 100 : 0,
|
||||
state: ready ? "PASS_100" : "FAIL_0",
|
||||
service_receipts: serviceReceipts,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
import assert from "node:assert/strict";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import {
|
||||
ExecutionObserver,
|
||||
REQUIRED_PROTOCOL_CHAIN,
|
||||
} from "./execution-observer.mjs";
|
||||
|
||||
test("observes allowlisted Linux services through typed read-only requests", async () => {
|
||||
const stateRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), "guanghu-execution-observer-"),
|
||||
);
|
||||
const calls = [];
|
||||
const observer = new ExecutionObserver({
|
||||
binaryPath: "/opt/guanghu/execution-bridge/current/guanghu-execution-bridge",
|
||||
policyPath: "/opt/guanghu/execution-bridge/current/policy.json",
|
||||
stateRoot,
|
||||
services: ["guanghu-ai-discovery.service", "lake-lamp-authz.service"],
|
||||
execute: async (program, argv) => {
|
||||
const request = JSON.parse(
|
||||
fs.readFileSync(argv[1], "utf8"),
|
||||
);
|
||||
calls.push({ program, argv, request });
|
||||
return {
|
||||
stdout: JSON.stringify({
|
||||
schema: "guanghu.execution-receipt/v1",
|
||||
request_id: request.request_id,
|
||||
subject_id: request.subject_id,
|
||||
target_node_id: request.target_node_id,
|
||||
policy_id: "JD-FD-PRIMARY-READONLY-20260807",
|
||||
action: request.action,
|
||||
adapter: "LINUX_SYSTEMD_V1",
|
||||
accepted: true,
|
||||
command_exit_code: 0,
|
||||
target_state_verified: true,
|
||||
final_state: "PASS_100",
|
||||
stdout: "active",
|
||||
stderr: "",
|
||||
rollback_checkpoint_id: null,
|
||||
}),
|
||||
stderr: "",
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
const projection = await observer.observe();
|
||||
assert.equal(projection.state, "PASS_100");
|
||||
assert.equal(projection.bridge_bound, 100);
|
||||
assert.equal(projection.target_state_verified, 100);
|
||||
assert.equal(projection.restart_allowed, false);
|
||||
assert.equal(projection.arbitrary_shell, false);
|
||||
assert.equal(calls.length, 2);
|
||||
assert.equal(calls[0].argv[0], "execute");
|
||||
assert.deepEqual(calls[0].request.protocol_chain, REQUIRED_PROTOCOL_CHAIN);
|
||||
assert.equal(calls[0].request.action.kind, "service_status");
|
||||
assert.equal(calls[0].request.authorization, null);
|
||||
assert.equal(calls[0].request.rollback, null);
|
||||
});
|
||||
|
||||
test("fails closed when the native receipt does not match the requested service", async () => {
|
||||
const stateRoot = fs.mkdtempSync(
|
||||
path.join(os.tmpdir(), "guanghu-execution-observer-"),
|
||||
);
|
||||
const observer = new ExecutionObserver({
|
||||
binaryPath: "/bridge",
|
||||
policyPath: "/policy",
|
||||
stateRoot,
|
||||
services: ["guanghu-ai-discovery.service"],
|
||||
execute: async () => ({
|
||||
stdout: JSON.stringify({
|
||||
schema: "guanghu.execution-receipt/v1",
|
||||
target_node_id: "JD-FD-PRIMARY",
|
||||
action: {
|
||||
kind: "service_status",
|
||||
resource: "different.service",
|
||||
},
|
||||
adapter: "LINUX_SYSTEMD_V1",
|
||||
}),
|
||||
stderr: "",
|
||||
}),
|
||||
});
|
||||
|
||||
await assert.rejects(
|
||||
() => observer.observe(),
|
||||
/execution_receipt_contract_mismatch/,
|
||||
);
|
||||
});
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env node
|
||||
import http from "node:http";
|
||||
import { ControllerEngine, bootEvent } from "./controller-engine.mjs";
|
||||
import { ExecutionObserver } from "./execution-observer.mjs";
|
||||
import { DeepSeekJsonClient } from "./model-client.mjs";
|
||||
import { MachineNavigation } from "./machine-navigation.mjs";
|
||||
|
||||
|
|
@ -10,6 +11,16 @@ const STATE_ROOT =
|
|||
process.env.BS_TCS_CONTROLLER_STATE_ROOT ||
|
||||
"/var/lib/guanghu/personas/bingshuo-tcs";
|
||||
const MODEL = process.env.DEEPSEEK_MODEL || "deepseek-chat";
|
||||
const EXECUTION_BRIDGE_BIN =
|
||||
process.env.GUANGHU_EXECUTION_BRIDGE_BIN ||
|
||||
"/opt/guanghu/execution-bridge/current/guanghu-execution-bridge";
|
||||
const EXECUTION_BRIDGE_POLICY =
|
||||
process.env.GUANGHU_EXECUTION_BRIDGE_POLICY ||
|
||||
"/opt/guanghu/execution-bridge/current/policy.json";
|
||||
const EXECUTION_OBSERVE_INTERVAL_MS = Math.max(
|
||||
10_000,
|
||||
Number(process.env.GUANGHU_EXECUTION_OBSERVE_INTERVAL_MS || 30_000),
|
||||
);
|
||||
const MAX_BODY_BYTES = 16 * 1024;
|
||||
|
||||
const runtime = {
|
||||
|
|
@ -19,6 +30,16 @@ const runtime = {
|
|||
last_event_id: null,
|
||||
last_error: null,
|
||||
receipt: null,
|
||||
execution_substrate: {
|
||||
schema: "guanghu.cognitive-execution-observation/v1",
|
||||
target_node_id: "JD-FD-PRIMARY",
|
||||
mode: "READ_ONLY_STATUS",
|
||||
bridge_bound: 0,
|
||||
target_state_verified: 0,
|
||||
restart_allowed: false,
|
||||
arbitrary_shell: false,
|
||||
state: "NOT_YET_OBSERVED",
|
||||
},
|
||||
};
|
||||
|
||||
const engine = new ControllerEngine({
|
||||
|
|
@ -27,6 +48,29 @@ const engine = new ControllerEngine({
|
|||
modelName: MODEL,
|
||||
});
|
||||
const navigation = new MachineNavigation();
|
||||
const executionObserver = new ExecutionObserver({
|
||||
binaryPath: EXECUTION_BRIDGE_BIN,
|
||||
policyPath: EXECUTION_BRIDGE_POLICY,
|
||||
stateRoot: STATE_ROOT,
|
||||
});
|
||||
|
||||
async function refreshExecutionSubstrate() {
|
||||
try {
|
||||
runtime.execution_substrate = await executionObserver.observe();
|
||||
} catch (error) {
|
||||
runtime.execution_substrate = {
|
||||
schema: "guanghu.cognitive-execution-observation/v1",
|
||||
target_node_id: "JD-FD-PRIMARY",
|
||||
mode: "READ_ONLY_STATUS",
|
||||
bridge_bound: 0,
|
||||
target_state_verified: 0,
|
||||
restart_allowed: false,
|
||||
arbitrary_shell: false,
|
||||
state: "FAIL_0",
|
||||
error: String(error.message || error).slice(0, 240),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function send(response, status, body) {
|
||||
const payload = JSON.stringify(body);
|
||||
|
|
@ -63,6 +107,7 @@ function health() {
|
|||
persona_brain_runtime_exists: existence.persona_brain_runtime_exists || 0,
|
||||
living_ai_system_controller_running:
|
||||
existence.living_ai_system_controller_running || 0,
|
||||
execution_substrate: runtime.execution_substrate,
|
||||
...navigationHealth,
|
||||
};
|
||||
}
|
||||
|
|
@ -202,6 +247,12 @@ server.listen(PORT, HOST, () => {
|
|||
port: PORT,
|
||||
})}\n`,
|
||||
);
|
||||
void refreshExecutionSubstrate();
|
||||
const executionObservationTimer = setInterval(
|
||||
() => void refreshExecutionSubstrate(),
|
||||
EXECUTION_OBSERVE_INTERVAL_MS,
|
||||
);
|
||||
executionObservationTimer.unref();
|
||||
if (runtime.phase === "PAUSED_FOR_HUMAN") return;
|
||||
eventQueue = handleEvent(bootEvent()).catch((error) => {
|
||||
runtime.phase = "FAILED_CLOSED";
|
||||
|
|
|
|||
Loading…
Reference in a new issue