feat(paths): enforce fifth-domain physical redirects
This commit is contained in:
parent
28a60b4e80
commit
c180a12d8d
15 changed files with 350 additions and 18 deletions
|
|
@ -2,6 +2,7 @@
|
|||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import process from "node:process";
|
||||
import { classifyPath } from "../fifth-domain-path-gate/fifth-domain-path-gate.mjs";
|
||||
|
||||
const POLICY_PATH = "/Volumes/JZAO/HoloLake/persona-runtime/repo-012-main/routing/persona-host-write-boundary.json";
|
||||
const policy = JSON.parse(fs.readFileSync(POLICY_PATH, "utf8"));
|
||||
|
|
@ -36,11 +37,32 @@ function protectedTarget(resolved) {
|
|||
return policy.canonical_protected_roots.some(item => patternRegex(item).test(resolved));
|
||||
}
|
||||
|
||||
function sensitiveHostEntryTarget(resolved) {
|
||||
return (policy.sensitive_host_entry_paths || []).some(item => patternRegex(item).test(resolved));
|
||||
}
|
||||
|
||||
function isAllowed(host, target) {
|
||||
const rule = policy.hosts[host];
|
||||
if (!rule) return { allowed: false, code: "HOST_UNKNOWN" };
|
||||
if (rule.write_mode.startsWith("READ_ONLY")) return { allowed: false, code: "HOST_READ_ONLY" };
|
||||
const resolved = normal(target);
|
||||
const hostRoot = rule.allowed_write_roots.find((item) => patternRegex(item).test(resolved));
|
||||
const preliminaryGate = classifyPath(resolved, hostRoot ? "BRANCH_WORK" : "CANONICAL_WRITE");
|
||||
if ([78, 79].includes(preliminaryGate.exit_code)) {
|
||||
const console = activeConsole(host);
|
||||
const matched = console?.write_roots?.find((item) => patternRegex(item).test(resolved));
|
||||
const maintenance = /PATH_CONVERGENCE|PHYSICAL_RETIREMENT/.test(console?.execution_semantics || "");
|
||||
if (matched && maintenance) return { allowed: true, code: "ACTIVE_ZERO_CORE_CONSOLE_RETIRED_PATH_MAINTENANCE_SCOPE", resolved, matched, console_id: console.console_id };
|
||||
return { allowed: false, code: `FIFTH_DOMAIN_${preliminaryGate.code}`, resolved, redirect_to: preliminaryGate.redirect_to, history: preliminaryGate.history };
|
||||
}
|
||||
if (sensitiveHostEntryTarget(resolved)) {
|
||||
const console = activeConsole(host);
|
||||
const matched = console?.write_roots?.find((item) => patternRegex(item).test(resolved));
|
||||
return matched
|
||||
? { allowed: true, code: "ACTIVE_ZERO_CORE_CONSOLE_SENSITIVE_HOST_ENTRY_SCOPE", resolved, matched, console_id: console.console_id }
|
||||
: { allowed: false, code: "SENSITIVE_HOST_ENTRY_REQUIRES_ACTIVE_ZERO_CORE_CONSOLE", resolved };
|
||||
}
|
||||
if (hostRoot) return { allowed: true, code: "WITHIN_HOST_WRITE_ROOT", resolved, matched: hostRoot };
|
||||
if (protectedTarget(resolved)) {
|
||||
const console = activeConsole(host);
|
||||
const matched = console?.write_roots?.find((item) => patternRegex(item).test(resolved));
|
||||
|
|
@ -48,10 +70,7 @@ function isAllowed(host, target) {
|
|||
? { allowed: true, code: "ACTIVE_ZERO_CORE_CONSOLE_TASK_SCOPE", resolved, matched, console_id: console.console_id }
|
||||
: { allowed: false, code: "PROTECTED_ROOT_REQUIRES_ACTIVE_ZERO_CORE_CONSOLE", resolved };
|
||||
}
|
||||
const matched = rule.allowed_write_roots.find((item) => patternRegex(item).test(resolved));
|
||||
return matched
|
||||
? { allowed: true, code: "WITHIN_HOST_WRITE_ROOT", resolved, matched }
|
||||
: { allowed: false, code: "WRITE_OUTSIDE_HOST_ROOT", resolved };
|
||||
return { allowed: false, code: "WRITE_OUTSIDE_HOST_ROOT", resolved };
|
||||
}
|
||||
|
||||
function emit(result, hook = false) {
|
||||
|
|
@ -93,10 +112,22 @@ const MUTATING_SHELL = /(?:^|[;&|\s])(?:rm|mv|cp|install|mkdir|rmdir|touch|chmod
|
|||
function evaluateHook(host, input) {
|
||||
const tool = String(input.tool_name || input.toolName || "");
|
||||
const toolInput = input.tool_input || input.toolInput || {};
|
||||
if (READ_TOOLS.has(tool)) return { allowed: true, code: "READ_ONLY_TOOL", host, tool };
|
||||
if (READ_TOOLS.has(tool)) {
|
||||
for (const candidate of collectPathValues(toolInput)) {
|
||||
const gated = classifyPath(candidate, "CURRENT_SELECTION");
|
||||
if ([78, 79].includes(gated.exit_code)) return { allowed: false, code: `FIFTH_DOMAIN_${gated.code}`, host, tool, resolved: gated.resolved, redirect_to: gated.redirect_to, history: gated.history };
|
||||
}
|
||||
return { allowed: true, code: "READ_ONLY_TOOL", host, tool };
|
||||
}
|
||||
if (tool === "Bash") {
|
||||
const command = String(toolInput.command || "");
|
||||
if (!MUTATING_SHELL.test(command)) return { allowed: true, code: "READ_ONLY_SHELL", host, tool };
|
||||
if (!MUTATING_SHELL.test(command)) {
|
||||
for (const candidate of shellPaths(command)) {
|
||||
const gated = classifyPath(candidate, "CURRENT_SELECTION");
|
||||
if ([78, 79].includes(gated.exit_code)) return { allowed: false, code: `FIFTH_DOMAIN_${gated.code}`, host, tool, resolved: gated.resolved, redirect_to: gated.redirect_to, history: gated.history };
|
||||
}
|
||||
return { allowed: true, code: "READ_ONLY_SHELL", host, tool };
|
||||
}
|
||||
const rule = policy.hosts[host];
|
||||
if (!rule || rule.write_mode.startsWith("READ_ONLY")) return { allowed: false, code: "HOST_READ_ONLY", host, tool };
|
||||
const candidates = shellPaths(command);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ assert.equal(check("qwen", "/Volumes/JZAO/铸渊-ICE-GL-ZY001/ZCODE-DEV-20260906
|
|||
assert.equal(check("zcode", "/Volumes/JZAO/铸渊-ICE-GL-ZY001/ZCODE-DEV-20260906/a.txt").code, 0);
|
||||
assert.equal(check("zcode", "/Volumes/JZAO/铸渊-ICE-GL-ZY001/AGENTS.md").code, 2);
|
||||
assert.equal(check("qoder", "/Users/bingshuolingdianyuanhe/.qoder/skills/a.txt").code, 2);
|
||||
assert.equal(check("codex", "/Volumes/JZAO/HoloLake/persona-runtime/repo-012-main/routing/a.json").code, 0);
|
||||
assert.equal(check("codex", "/Volumes/JZAO/HoloLake/persona-runtime/repo-012-main/routing/path-isolation-and-canonical-entry-map.json").code, 0);
|
||||
|
||||
const deniedEdit = hook("zcode", { tool_name: "Edit", tool_input: { file_path: "/Volumes/JZAO/HoloLake/persona-runtime/repo-012-main/routing/a.json" } });
|
||||
assert.equal(deniedEdit.code, 2);
|
||||
|
|
@ -39,4 +39,13 @@ const allowedRead = hook("zcode", { tool_name: "Read", tool_input: { file_path:
|
|||
assert.equal(allowedRead.code, 0);
|
||||
assert.equal(allowedRead.body.hookSpecificOutput.permissionDecision, "allow");
|
||||
|
||||
console.log("HOST_WRITE_ADMISSION_TESTS_PASS 12/12");
|
||||
const retiredRead = hook("zcode", { tool_name: "Read", tool_input: { file_path: "/Volumes/JZAO/铸渊-ICE-GL-ZY001/WORK-工作区/guanghu-ice-heart/routing/guanghu-era-language-world.json" } });
|
||||
assert.equal(retiredRead.code, 2);
|
||||
assert.equal(retiredRead.body.hookSpecificOutput.permissionDecision, "deny");
|
||||
assert.match(retiredRead.body.hookSpecificOutput.permissionDecisionReason, /REDIRECT/);
|
||||
|
||||
const retiredShellRead = hook("zcode", { tool_name: "Bash", tool_input: { command: "sed -n '1,20p' /Users/bingshuolingdianyuanhe/.qoderworkcn/workspace/msj12fljjywpql1y/repo-work/repo012/INDEX.hdlp" } });
|
||||
assert.equal(retiredShellRead.code, 2);
|
||||
assert.equal(retiredShellRead.body.hookSpecificOutput.permissionDecision, "deny");
|
||||
|
||||
console.log("HOST_WRITE_ADMISSION_TESTS_PASS 18/18");
|
||||
|
|
|
|||
Loading…
Reference in a new issue