refactor(permission-system): simplify policy and autoreview flow

This commit is contained in:
云服务部-叶林立
2026-09-03 02:01:06 +08:00
parent 180da95ab7
commit 6e7effa792
112 changed files with 911 additions and 10346 deletions
@@ -84,45 +84,6 @@ describe("PathNormalizer", () => {
expect(normalizer.isWithinDirectory("/a/x", "/a/b")).toBe(false);
});
test("isOutsideWorkingDirectory tests against the baked cwd", () => {
expect(normalizer.isOutsideWorkingDirectory("/projects/my-app/src")).toBe(
false,
);
expect(normalizer.isOutsideWorkingDirectory("/etc/hosts")).toBe(true);
});
test("isOutsideWorkingDirectory expands a home-relative token", () => {
expect(normalizer.isOutsideWorkingDirectory("~/secrets")).toBe(true);
});
test("isOutsideWorkingDirectory resolves a relative token inside cwd", () => {
expect(normalizer.isOutsideWorkingDirectory("src/index.ts")).toBe(false);
});
test("isOutsideWorkingDirectory follows an in-cwd symlink to an external target", () => {
// ./link -> /etc: realpathSync resolves the full token in one call.
realpathSync.mockImplementation((p: string) => {
if (p === "/projects/my-app/link/hosts") return "/etc/hosts";
return p;
});
expect(normalizer.isOutsideWorkingDirectory("./link/hosts")).toBe(true);
});
test("isOutsideWorkingDirectory keeps a path inside a symlinked cwd", () => {
// /tmp -> /private/tmp on macOS; cwd reported as the resolved /private/tmp.
realpathSync.mockImplementation((p: string) => {
if (p.startsWith("/tmp/")) return `/private/tmp${p.slice(4)}`;
if (p === "/tmp") return "/private/tmp";
return p;
});
const symlinkNormalizer = new PathNormalizer(
posixPathFlavor,
"/private/tmp",
);
expect(
symlinkNormalizer.isOutsideWorkingDirectory("/tmp/workspace/file.ts"),
).toBe(false);
});
test("comparableValue returns the lexical absolute form (no FS)", () => {
expect(normalizer.comparableValue("src/foo.ts")).toBe(
@@ -136,20 +97,6 @@ describe("PathNormalizer", () => {
expect(ap.value()).toBe("/projects/my-app/src/foo.ts");
});
test("isBoundaryOutsideWorkingDirectory tests a canonical path against cwd", () => {
expect(
normalizer.isBoundaryOutsideWorkingDirectory("/projects/my-app/src"),
).toBe(false);
expect(normalizer.isBoundaryOutsideWorkingDirectory("/etc/hosts")).toBe(
true,
);
});
test("isBoundaryOutsideWorkingDirectory excludes a safe device path", () => {
expect(normalizer.isBoundaryOutsideWorkingDirectory("/dev/null")).toBe(
false,
);
});
test("interpretBashCdTarget maps an absolute target to absolute (posix)", () => {
expect(normalizer.interpretBashCdTarget("/etc")).toEqual({
@@ -199,12 +146,6 @@ describe("PathNormalizer", () => {
).toBe(true);
});
test("isOutsideWorkingDirectory case-folds against the baked cwd", () => {
expect(
normalizer.isOutsideWorkingDirectory("c:\\projects\\app\\src"),
).toBe(false);
expect(normalizer.isOutsideWorkingDirectory("C:\\Other\\dir")).toBe(true);
});
test("comparableValue case-folds the lexical absolute form", () => {
expect(normalizer.comparableValue("src\\foo.ts")).toBe(
@@ -216,9 +157,6 @@ describe("PathNormalizer", () => {
const ap = normalizer.forBashToken("/dev/null");
expect(ap.value()).toBe("/dev/null");
expect(ap.boundaryValue()).toBe("/dev/null");
expect(
normalizer.isBoundaryOutsideWorkingDirectory(ap.boundaryValue()),
).toBe(false);
});
test("forBashToken preserves all four safe device paths", () => {
@@ -235,17 +173,11 @@ describe("PathNormalizer", () => {
test("forBashToken translates an MSYS drive mount to a Windows path", () => {
const ap = normalizer.forBashToken("/c/Other/x");
expect(ap.value()).toBe("c:\\other\\x");
expect(
normalizer.isBoundaryOutsideWorkingDirectory(ap.boundaryValue()),
).toBe(true);
});
test("forBashToken translates an in-cwd drive mount (not external)", () => {
test("forBashToken translates an in-cwd drive mount", () => {
const ap = normalizer.forBashToken("/c/projects/app/inside.txt");
expect(ap.value()).toBe("c:\\projects\\app\\inside.txt");
expect(
normalizer.isBoundaryOutsideWorkingDirectory(ap.boundaryValue()),
).toBe(false);
});
test("forBashToken keeps a non-mount POSIX absolute as a literal", () => {
@@ -283,45 +215,8 @@ describe("PathNormalizer", () => {
});
});
test("isBoundaryOutsideWorkingDirectory case-folds against the baked cwd", () => {
expect(
normalizer.isBoundaryOutsideWorkingDirectory("c:\\projects\\app\\src"),
).toBe(false);
expect(
normalizer.isBoundaryOutsideWorkingDirectory("c:\\other\\dir"),
).toBe(true);
});
});
describe("isInfrastructureRead", () => {
const normalizer = new PathNormalizer(posixPathFlavor, "/projects/my-app");
test("allows a read-only tool targeting a configured infra dir", () => {
const ap = normalizer.forPath("/infra/git/pkg/SKILL.md");
expect(normalizer.isInfrastructureRead("read", ap, ["/infra"])).toBe(
true,
);
});
test("does not allow a write tool targeting an infra dir", () => {
const ap = normalizer.forPath("/infra/git/pkg/file.ts");
expect(normalizer.isInfrastructureRead("write", ap, ["/infra"])).toBe(
false,
);
});
test("does not allow a read-only tool outside any infra dir", () => {
const ap = normalizer.forPath("/elsewhere/file.ts");
expect(normalizer.isInfrastructureRead("read", ap, ["/infra"])).toBe(
false,
);
});
test("allows a read targeting the project-local .pi/npm dir (from baked cwd)", () => {
const ap = normalizer.forPath("/projects/my-app/.pi/npm/dep/index.js");
expect(normalizer.isInfrastructureRead("read", ap, [])).toBe(true);
});
});
describe("entryExists", () => {
// Real filesystem: the probe's whole purpose is to consult fs state, so