208 lines
6.7 KiB
JavaScript
208 lines
6.7 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { execFileSync } from "node:child_process";
|
|
import test from "node:test";
|
|
import { createRequire } from "node:module";
|
|
import { runDaily } from "./fifth-domain-daily-orchestrator.mjs";
|
|
|
|
const require = createRequire(import.meta.url);
|
|
const { validateUnit } = require(
|
|
"../lake-lamp-authz/architecture-provision-broker.js"
|
|
);
|
|
|
|
function git(args, options = {}) {
|
|
return execFileSync("/usr/bin/git", args, {
|
|
encoding: "utf8",
|
|
...options,
|
|
}).trim();
|
|
}
|
|
|
|
function createRepository(root, name, commits = 1) {
|
|
const work = path.join(root, `${name}-work`);
|
|
const bare = path.join(root, `${name}.git`);
|
|
fs.mkdirSync(work);
|
|
git(["init", "-b", "main"], { cwd: work });
|
|
git(["config", "user.name", "fixture"], { cwd: work });
|
|
git(["config", "user.email", "fixture@example.test"], { cwd: work });
|
|
for (let index = 1; index <= commits; index += 1) {
|
|
fs.writeFileSync(
|
|
path.join(work, `record-${index}.md`),
|
|
`# record ${index}\n`,
|
|
);
|
|
git(["add", "."], { cwd: work });
|
|
git(["commit", "-m", `record ${index}`], { cwd: work });
|
|
}
|
|
git(["clone", "--bare", work, bare]);
|
|
return { work, bare };
|
|
}
|
|
|
|
test("Zhuyuan daily dispatch writes one signed role update per advanced source", async () => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "persona-daily-"));
|
|
try {
|
|
const source = createRepository(root, "source", 3);
|
|
const names = [
|
|
["chenglu-agent", "CHENGLU-AGENT-001", "澄路"],
|
|
["guideng", "GUIDENG-AGENT-001", "归灯"],
|
|
["kezhou", "ICE-GL-KZ-001", "刻舟"],
|
|
];
|
|
const keys = new Map();
|
|
const members = names.map(([slug, personaId, name], index) => {
|
|
const target = createRepository(root, slug, 1);
|
|
const pair = crypto.generateKeyPairSync("ed25519");
|
|
const publicKey = pair.publicKey.export({
|
|
type: "spki",
|
|
format: "pem",
|
|
});
|
|
const fingerprint = `SHA256:${crypto
|
|
.createHash("sha256")
|
|
.update(
|
|
pair.publicKey.export({
|
|
type: "spki",
|
|
format: "der",
|
|
}),
|
|
)
|
|
.digest("base64")
|
|
.replace(/=+$/, "")}`;
|
|
keys.set(personaId, { privateKey: pair.privateKey, publicKey });
|
|
return {
|
|
slug,
|
|
persona_id: personaId,
|
|
name,
|
|
endpoint: `http://127.0.0.1:${4100 + index}/observe`,
|
|
identity_fingerprint: fingerprint,
|
|
target_repository: target.bare,
|
|
commit_email: `${slug}@example.test`,
|
|
controller_token: "fixture-controller-token",
|
|
scoped_duties: ["bounded fixture duty"],
|
|
};
|
|
});
|
|
let requestCount = 0;
|
|
const fetchImpl = async (_url, request) => {
|
|
requestCount += 1;
|
|
const event = JSON.parse(request.body);
|
|
const member = members.find(
|
|
(candidate) =>
|
|
!Array.from(keys.keys()).every(
|
|
(personaId) => personaId !== candidate.persona_id,
|
|
) && candidate.endpoint === _url,
|
|
);
|
|
const key = keys.get(member.persona_id);
|
|
const payload = {
|
|
schema: "guanghu.fifth-domain-persona-observation-payload/v1",
|
|
persona_id: member.persona_id,
|
|
arrival_id: "fixture-arrival",
|
|
team_controller_id: "ICE-P-ZY001",
|
|
caller_nonce: event.caller_nonce,
|
|
role: "fixture-role",
|
|
source: event.source,
|
|
observation: {
|
|
schema: "guanghu.fifth-domain-persona-observation/v1",
|
|
persona_id: member.persona_id,
|
|
team_controller_id: "ICE-P-ZY001",
|
|
caller_nonce: event.caller_nonce,
|
|
source_to_sha: event.source.to_sha,
|
|
summary: `${member.name}完成第五域岗位更新`,
|
|
role_findings: ["fixture finding"],
|
|
self_updates: ["fixture self update"],
|
|
recommended_actions: [],
|
|
questions: [],
|
|
boundary_note: "fixture boundary",
|
|
},
|
|
model: { provider: "fixture", name: "fixture" },
|
|
issued_at: "2026-08-06T00:00:00.000Z",
|
|
};
|
|
return {
|
|
ok: true,
|
|
async json() {
|
|
return {
|
|
ok: true,
|
|
persona_id: member.persona_id,
|
|
identity_fingerprint: member.identity_fingerprint,
|
|
public_key: key.publicKey,
|
|
payload,
|
|
signature: crypto
|
|
.sign(null, Buffer.from(JSON.stringify(payload)), key.privateKey)
|
|
.toString("base64"),
|
|
signature_algorithm: "Ed25519",
|
|
};
|
|
},
|
|
};
|
|
};
|
|
const config = {
|
|
source_repository: source.bare,
|
|
runtime_root: path.join(root, "runtime"),
|
|
bootstrap_commit_window: 20,
|
|
members,
|
|
};
|
|
const first = await runDaily(config, {
|
|
fetchImpl,
|
|
now: "2026-08-06T00:00:00.000Z",
|
|
});
|
|
assert.equal(first.result, "PASS");
|
|
assert.equal(requestCount, 3);
|
|
assert.ok(
|
|
first.results.every(
|
|
(result) => result.status === "FIFTH_DOMAIN_UPDATE_COMMITTED",
|
|
),
|
|
);
|
|
const sourceSha = git([`--git-dir=${source.bare}`, "rev-parse", "main"]);
|
|
for (const member of members) {
|
|
const current = JSON.parse(
|
|
git([
|
|
`--git-dir=${member.target_repository}`,
|
|
"show",
|
|
"main:persona-system/fifth-domain/CURRENT.json",
|
|
]),
|
|
);
|
|
assert.equal(current.last_source_sha, sourceSha);
|
|
assert.equal(current.controller, "ICE-P-ZY001");
|
|
}
|
|
|
|
const second = await runDaily(config, {
|
|
fetchImpl,
|
|
now: "2026-08-07T00:00:00.000Z",
|
|
});
|
|
assert.equal(second.result, "PASS");
|
|
assert.equal(requestCount, 3);
|
|
assert.ok(
|
|
second.results.every(
|
|
(result) => result.status === "NO_NEW_FIFTH_DOMAIN_COMMIT",
|
|
),
|
|
);
|
|
} finally {
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("daily dispatcher unit is hardened and restricted to exact persona repositories", () => {
|
|
const root = path.resolve(path.dirname(new URL(import.meta.url).pathname), "../..");
|
|
const unit = fs.readFileSync(
|
|
path.join(
|
|
root,
|
|
"server-tools/persona-team-handshake/zhuyuan-persona-fifth-domain-daily.service",
|
|
),
|
|
"utf8",
|
|
);
|
|
const base =
|
|
"/var/lib/guanghu/personas/guanghu/hlcc-v16.0.1/data/repositories/bingshuo";
|
|
assert.equal(
|
|
validateUnit(unit, "guanghu", {
|
|
environment_files: [
|
|
"/etc/guanghu/persona-secrets/shared-deepseek.env",
|
|
],
|
|
read_only_paths: [
|
|
"/var/lib/guanghu/personas/guanghu/hlcc-v16.0.1/data/repositories/bingshuo/guanghu-ice-heart.git",
|
|
],
|
|
writable_paths: [
|
|
"/var/lib/guanghu/personas/guanghu/fifth-domain-daily",
|
|
`${base}/chenglu-agent.git`,
|
|
`${base}/guideng.git`,
|
|
`${base}/kezhou.git`,
|
|
],
|
|
}),
|
|
unit,
|
|
);
|
|
});
|