汇总已落盘的借款本金与还款、兼容历史编号的周期化编号、付款责任与回单核验、报销进度和排序、PWA/采购事务、错误原因与日期校验及ERP退役。 统一共享预算池锁序和锁后判断,恢复差旅原预算选择,补原因码固定夹具及反向完整性检查。 纳入配套迁移、测试、受管QA、分层验收合同、规约及任务记录;原始证据留在ignored artifacts。 关联任务:09-17-company-loan-principal-repayment、09-17-erp-exclusive-retirement、09-18-reimbursement-periodic-numbering、09-08-reimbursement-payment-closeout、09-18-local-concurrency-product-fixes、09-19-budget-pool-concurrency、09-05-error-explainability-payment-readiness。 预算补审由Claude定向验证2文件928项通过,原4446/28及r6结果仍仅对应各自历史输入;本轮未重跑测试。 完整新候选门禁、R1真实入口接入与12项公网义务仍开放。生产编号未启用、差旅仍冻结;不推送、不部署,不宣称发布资格。
124 行
8.3 KiB
JavaScript
124 行
8.3 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { spawnSync } from "node:child_process";
|
|
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, rmSync } from "node:fs";
|
|
import path from "node:path";
|
|
import os from "node:os";
|
|
import { fileURLToPath } from "node:url";
|
|
import { createServer } from "node:net";
|
|
import { topologyMatches, validateEnvironmentFacts, validateEnvironmentReceipt, verifyManagedEnvironment, requestSupervisorObservation } from "../full-local-environment.mjs";
|
|
|
|
function receipt() {
|
|
return {
|
|
schemaVersion: 1, profile: "isolated-online-v1", policyDigest: "policy",
|
|
supervisorObservation: { source: "live-supervisor-unix-ipc", sampledAt: "2026-09-07T00:00:00Z", namespace: "parent" },
|
|
namespace: { inheritedRunner: "parent", ownedChild: "child", runnerCreated: true, currentMatchesOwnedChild: true, topologyMatched: true },
|
|
nativeOnlineProbe: { valid: true, online: true, browserNamespace: "child", browserMatchesOwnedChild: true, noNavigatorOverride: true, engines: ["chromium", "webkit"].map(name => ({ name, version: "synthetic", online: true, valid: true, noNavigatorOverride: true, browserNamespace: "child", browserMatchesOwnedChild: true })) },
|
|
bootstrapObservation: {
|
|
valid: true, observationPoint: "guest-entry-black-box", freshContext: true, initialSessionHint: false,
|
|
listenerBeforeNavigation: true, noRouteMocks: true, loginFormVisible: true, refreshRequestCount: 0, loginRequestCount: 0,
|
|
nativeOnlineSamples: { beforeNavigation: true, documentStart: true, afterForm: true },
|
|
browserNamespace: "child", browserMatchesOwnedChild: true, noNavigatorOverride: true, documentStatus: 200, stayedOnLogin: true,
|
|
},
|
|
};
|
|
}
|
|
test("环境回执必须消费事实而非 valid 标记", () => {
|
|
assert.deepEqual(validateEnvironmentReceipt(receipt(), "policy"), []);
|
|
for (const section of ["namespace", "nativeOnlineProbe", "bootstrapObservation", "supervisorObservation"]) {
|
|
for (const key of Object.keys(receipt()[section])) {
|
|
const value = receipt();
|
|
delete value[section][key];
|
|
assert.ok(validateEnvironmentReceipt(value, "policy").length, `${section}.${key}`);
|
|
}
|
|
}
|
|
for (const mutate of [
|
|
value => { value.bootstrapObservation.refreshRequestCount = 1; },
|
|
value => { value.bootstrapObservation.nativeOnlineSamples.documentStart = false; },
|
|
value => { value.namespace.ownedChild = "parent"; },
|
|
value => { value.nativeOnlineProbe.browserNamespace = "other"; },
|
|
value => { value.policyDigest = "old"; },
|
|
]) {
|
|
const value = receipt(); mutate(value);
|
|
assert.ok(validateEnvironmentReceipt(value, "policy").length);
|
|
}
|
|
});
|
|
|
|
test("父 runner 实时 IPC 绑定本轮、进程和当前策略,错误响应拒绝", async context => {
|
|
const scratch = mkdtempSync(path.join(os.tmpdir(), "hyb-env-ipc-test-"));
|
|
const owner = { scratch, runId: "current", supervisorPid: process.pid, policyDigest: "policy" };
|
|
let observation = { runId: owner.runId, pid: owner.supervisorPid, policyDigest: owner.policyDigest, namespace: "parent" };
|
|
const server = createServer(connection => connection.end(JSON.stringify(observation)));
|
|
context.after(async () => { await new Promise(resolve => server.close(resolve)); rmSync(scratch, { recursive: true, force: true }); });
|
|
await new Promise(resolve => server.listen(path.join(scratch, "supervisor.sock"), resolve));
|
|
assert.equal((await requestSupervisorObservation(owner)).namespace, "parent");
|
|
for (const key of ["runId", "pid", "policyDigest", "namespace"]) {
|
|
const previous = observation;
|
|
observation = { ...previous, [key]: null };
|
|
await assert.rejects(requestSupervisorObservation(owner), /response_invalid/);
|
|
observation = previous;
|
|
}
|
|
await assert.rejects(requestSupervisorObservation({ ...owner, scratch: path.join(scratch, "missing") }), /unavailable/);
|
|
});
|
|
test("缺 context 不接受 GATE_PASSED 或已有 true", () => {
|
|
assert.throws(() => verifyManagedEnvironment(""), /context_required/);
|
|
const context = { schemaVersion: 1, profile: "isolated-online-v1", policyDigest: "policy", inheritedNamespace: "parent", ownedNamespace: "child" };
|
|
const facts = { policyDigest: "policy", supervisorRecognized: true, descendantOfSupervisor: true, supervisorNamespace: "parent", currentNamespace: "child", topologyMatched: true };
|
|
assert.deepEqual(validateEnvironmentFacts(context, facts), []);
|
|
for (const key of Object.keys(facts)) assert.ok(validateEnvironmentFacts(context, { ...facts, [key]: null }).length, key);
|
|
});
|
|
test("拓扑只接纳同 namespace 内部 veth 默认路由,拒绝外部对端和网关", () => {
|
|
const addresses = [{ ifname: "lo" }, ...["qaonline", "qapeer"].map((ifname, index) => ({ ifname, flags: ["UP"], operstate: "UP", addr_info: [{ local: `192.0.2.${index + 1}`, prefixlen: 30 }] }))];
|
|
const links = [{ifname:"lo",ifindex:1},{ifname:"qaonline",ifindex:2,link:"qapeer",linkinfo:{info_kind:"veth"}},{ifname:"qapeer",ifindex:3,link:"qaonline",linkinfo:{info_kind:"veth"}}];
|
|
const routes = [{dst:"default",dev:"qaonline",scope:"link"}];
|
|
assert.equal(topologyMatches(addresses, routes, [], links), true);
|
|
for(const mutate of [
|
|
f=>{f.routes=[];}, f=>{f.routes.push(f.routes[0]);}, f=>{f.routes[0].gateway="192.0.2.2";},
|
|
f=>{f.routes[0].dev="eth0";}, f=>{f.routes[0].scope="global";}, f=>{f.routes[0].multipath=[];},
|
|
f=>{f.ipv6=[{dst:"default",dev:"qaonline"}];}, f=>{f.addresses.push({ifname:"eth0"});},
|
|
f=>{f.links[1].link_netnsid=0;}, f=>{f.links[1].link="outside";}, f=>{f.links[1].linkinfo.info_kind="bridge";},
|
|
f=>{f.links[1].master="outside";}, f=>{f.links.pop();}, f=>{f.links=undefined;},
|
|
]) {
|
|
const f=structuredClone({addresses,links,routes,ipv6:[]});mutate(f);
|
|
assert.equal(topologyMatches(f.addresses,f.routes,f.ipv6,f.links),false);
|
|
}
|
|
});
|
|
|
|
for (const mismatch of [false, true]) test(`namespace 创建失败不降级,清理须匹配 owner:mismatch=${mismatch}`, context => {
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../..");
|
|
const temporary = mkdtempSync(path.join(os.tmpdir(), "hyb-env-command-test-"));
|
|
const report = mkdtempSync(path.join(root, "artifacts/qa-flow/environment-command-test-"));
|
|
const commands = path.join(temporary, "commands.jsonl");
|
|
mkdirSync(path.join(temporary, "bin"));
|
|
context.after(() => {
|
|
try {
|
|
const owned = JSON.parse(readFileSync(path.join(report, "environment/context.private.json")));
|
|
assert.ok(path.basename(owned.scratch).startsWith("hyb-qa-managed-"));
|
|
rmSync(owned.scratch, { recursive: true, force: true });
|
|
} finally {
|
|
rmSync(temporary, { recursive: true, force: true });
|
|
rmSync(report, { recursive: true, force: true });
|
|
}
|
|
});
|
|
writeFileSync(path.join(temporary, "bin/docker"), `#!${process.execPath}
|
|
const fs = require('node:fs');
|
|
const args = process.argv.slice(2);
|
|
fs.appendFileSync(${JSON.stringify(commands)},JSON.stringify(args)+'\\n');
|
|
if (args[0] === 'image') console.log('sha256:synthetic');
|
|
if (args[0] === 'run') { fs.writeFileSync(${JSON.stringify(path.join(temporary, "owner"))},args[args.indexOf('--name')+1]); console.log('a'.repeat(64)); }
|
|
if (args[0] === 'inspect') console.log('a'.repeat(64)+'|'+(${mismatch} ? 'other-owner' : fs.readFileSync(${JSON.stringify(path.join(temporary, "owner"))},'utf8'))+'|none');
|
|
`, { mode: 0o755 });
|
|
writeFileSync(path.join(temporary, "bin/unshare"), "#!/bin/sh\nexit 1\n", { mode: 0o755 });
|
|
const result = spawnSync(process.execPath, [path.join(root, "scripts/qa/full-local-environment.mjs"), "full-local-diagnostic"], {
|
|
cwd: root, encoding: "utf8", timeout: 30000,
|
|
env: { PATH: `${path.join(temporary, "bin")}:${process.env.PATH}`, HOME: temporary, QA_DIAGNOSTIC_REPORT_DIR: report, QA_DIAGNOSTIC_REASON: "synthetic test", QA_DIAGNOSTIC_OPERATOR: "fixture", QA_DIAGNOSTIC_APPROVAL_REF: "fixture-only", ENVIRONMENT_PASSED: "1" },
|
|
});
|
|
assert.equal(result.status, 2, result.stderr);
|
|
const receipt = JSON.parse(readFileSync(path.join(report, "environment/result.json")));
|
|
assert.equal(receipt.status, "ENVIRONMENT_INVALID");
|
|
assert.equal(receipt.normalReleaseEligible, false);
|
|
assert.equal(receipt.cleanup.containerRemoved, !mismatch);
|
|
const calls = readFileSync(commands, "utf8").trim().split("\n").map(JSON.parse);
|
|
assert.equal(calls.some(args => args[0] === "rm"), !mismatch);
|
|
assert.ok(calls.find(args => args[0] === "run").includes("--pull=never"));
|
|
});
|