feat: vendor permission system source

This commit is contained in:
云服务部-叶林立
2026-08-19 14:35:19 +08:00
parent 198584daf8
commit 410c50a3e5
809 changed files with 157793 additions and 139 deletions
@@ -0,0 +1,245 @@
import { join } from "node:path";
import { beforeEach, describe, expect, test, vi } from "vitest";
// Mock node:os so tilde-expansion is deterministic across platforms.
vi.mock("node:os", () => {
const homedir = vi.fn(() => "/mock/home");
return {
homedir,
default: { homedir },
};
});
// Mock node:fs so realpathSync (used by canonicalizePath) is controllable.
// Default implementation is identity — existing lexical tests are unaffected.
const realpathSync = vi.hoisted(() =>
vi.fn<(path: string) => string>((p) => p),
);
vi.mock("node:fs", () => ({
realpathSync,
default: { realpathSync },
}));
import {
canonicalNormalizePathForComparison,
getPathPolicyValues,
normalizePathForComparison,
normalizePathPolicyLiteral,
} from "#src/access-intent/path-normalization";
import { posixPathFlavor, win32PathFlavor } from "#src/path/path-flavor";
describe("normalizePathForComparison", () => {
const cwd = "/projects/my-app";
test("resolves absolute path unchanged", () => {
expect(
normalizePathForComparison("/usr/local/bin", cwd, posixPathFlavor),
).toBe("/usr/local/bin");
});
test("resolves relative path against cwd", () => {
expect(normalizePathForComparison("src/foo.ts", cwd, posixPathFlavor)).toBe(
"/projects/my-app/src/foo.ts",
);
});
test("expands bare ~ to homedir", () => {
expect(normalizePathForComparison("~", cwd, posixPathFlavor)).toBe(
"/mock/home",
);
});
test("expands ~/... to homedir-relative path", () => {
expect(
normalizePathForComparison("~/docs/readme.md", cwd, posixPathFlavor),
).toBe(join("/mock/home", "docs/readme.md"));
});
test("expands bare $HOME to homedir", () => {
expect(normalizePathForComparison("$HOME", cwd, posixPathFlavor)).toBe(
"/mock/home",
);
});
test("expands $HOME/... to homedir-relative path", () => {
expect(
normalizePathForComparison("$HOME/.ssh/config", cwd, posixPathFlavor),
).toBe(join("/mock/home", ".ssh/config"));
});
test("strips leading @ before resolving", () => {
expect(
normalizePathForComparison("@/usr/local/bin", cwd, posixPathFlavor),
).toBe("/usr/local/bin");
});
test("strips surrounding quotes", () => {
expect(
normalizePathForComparison("'/usr/local/bin'", cwd, posixPathFlavor),
).toBe("/usr/local/bin");
expect(
normalizePathForComparison('"/usr/local/bin"', cwd, posixPathFlavor),
).toBe("/usr/local/bin");
});
test("returns empty string for blank/whitespace-only path", () => {
expect(normalizePathForComparison("", cwd, posixPathFlavor)).toBe("");
expect(normalizePathForComparison(" ", cwd, posixPathFlavor)).toBe("");
});
// ── injected platform flavor (Windows is case-folded, win32-resolved) ────
test("win32: lowercases the resolved absolute path", () => {
expect(
normalizePathForComparison(
"C:\\Users\\Foo\\Bar.txt",
"C:\\Projects",
win32PathFlavor,
),
).toBe("c:\\users\\foo\\bar.txt");
});
test("win32: resolves a relative path against cwd with win32 rules", () => {
expect(
normalizePathForComparison(
"src\\foo.ts",
"C:\\Projects\\App",
win32PathFlavor,
),
).toBe("c:\\projects\\app\\src\\foo.ts");
});
test("posix platform leaves case untouched", () => {
expect(
normalizePathForComparison("/Projects/App/Src.ts", cwd, posixPathFlavor),
).toBe("/Projects/App/Src.ts");
});
});
describe("canonicalNormalizePathForComparison", () => {
const cwd = "/projects/my-app";
beforeEach(() => {
realpathSync.mockReset();
realpathSync.mockImplementation((p: string) => p);
});
test("returns canonical form of an existing path", () => {
realpathSync.mockImplementation((p: string) => {
if (p === "/projects/link") return "/real/projects/app";
return p;
});
expect(
canonicalNormalizePathForComparison(
"/projects/link",
cwd,
posixPathFlavor,
),
).toBe("/real/projects/app");
});
test("returns empty string for empty input", () => {
expect(canonicalNormalizePathForComparison("", cwd, posixPathFlavor)).toBe(
"",
);
});
test("returns lexical form when no symlinks (identity realpathSync)", () => {
expect(
canonicalNormalizePathForComparison(
"/projects/my-app/src/index.ts",
cwd,
posixPathFlavor,
),
).toBe("/projects/my-app/src/index.ts");
});
test("win32: lowercases the canonical form", () => {
expect(
canonicalNormalizePathForComparison(
"C:\\Projects\\App\\Src",
"C:\\Projects\\App",
win32PathFlavor,
),
).toBe("c:\\projects\\app\\src");
});
});
describe("normalizePathPolicyLiteral", () => {
test("returns a relative token unchanged", () => {
expect(normalizePathPolicyLiteral("src/foo.ts")).toBe("src/foo.ts");
});
test("trims and strips simple wrapping quotes", () => {
expect(normalizePathPolicyLiteral(" 'src/foo.ts' ")).toBe("src/foo.ts");
expect(normalizePathPolicyLiteral('"a/b"')).toBe("a/b");
});
test("strips a leading @ prefix", () => {
expect(normalizePathPolicyLiteral("@src/foo.ts")).toBe("src/foo.ts");
});
test("expands ~ to the home directory", () => {
expect(normalizePathPolicyLiteral("~/docs/readme.md")).toBe(
join("/mock/home", "docs/readme.md"),
);
});
test("does not resolve a relative value against any cwd", () => {
expect(normalizePathPolicyLiteral("foo.ts")).toBe("foo.ts");
});
test("returns empty string for blank input", () => {
expect(normalizePathPolicyLiteral(" ")).toBe("");
});
test("preserves the surface catch-all", () => {
expect(normalizePathPolicyLiteral("*")).toBe("*");
});
});
describe("getPathPolicyValues", () => {
const cwd = "/projects/my-app";
test("returns only the literal when no base is available", () => {
expect(getPathPolicyValues("src/foo.ts", {}, posixPathFlavor)).toEqual([
"src/foo.ts",
]);
expect(getPathPolicyValues("src/foo.ts", {}, posixPathFlavor)).toEqual([
"src/foo.ts",
]);
});
test("adds absolute and project-relative aliases for a relative token", () => {
expect(getPathPolicyValues("src/foo.ts", { cwd }, posixPathFlavor)).toEqual(
["/projects/my-app/src/foo.ts", "src/foo.ts"],
);
});
test("omits the relative alias for a token outside cwd", () => {
expect(getPathPolicyValues("/etc/hosts", { cwd }, posixPathFlavor)).toEqual(
["/etc/hosts"],
);
});
test("resolves against resolveBase while aliasing relative to cwd", () => {
expect(
getPathPolicyValues(
"foo.txt",
{
cwd,
resolveBase: "/projects/my-app/nested",
},
posixPathFlavor,
),
).toEqual(["/projects/my-app/nested/foo.txt", "nested/foo.txt", "foo.txt"]);
});
test("preserves the surface catch-all", () => {
expect(getPathPolicyValues("*", { cwd }, posixPathFlavor)).toEqual(["*"]);
});
test("returns empty for blank input", () => {
expect(getPathPolicyValues(" ", { cwd }, posixPathFlavor)).toEqual([]);
});
});