refactor(scum): remove unverified manifest templates

This commit is contained in:
npc0-hue
2026-08-11 15:34:45 +08:00
parent 13746150cb
commit d77068ce78
26 changed files with 26 additions and 624 deletions
+17 -23
View File
@@ -191,16 +191,15 @@ describe("plugin manifest validation", () => {
expect(validateManifestFile("examples/scum-server-plugin/manifest.json")).toEqual([]);
});
it("removes raw protected SQL and management request command surfaces", () => {
it("removes unverified SCUM query and operation declarations", () => {
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as { gameClientBridge: { commands: Array<{ type: string; protectedRequest?: { kind: string } }>; queryTemplates: Array<{ key: string }>; operationTemplates: Array<{ key: string; kind: string }> } };
const commands = manifest.gameClientBridge.commands.filter((candidate) => candidate.protectedRequest);
expect(commands).toEqual([]);
expect(manifest.gameClientBridge.commands.map((command) => command.type)).not.toEqual(expect.arrayContaining(["config.read", "config.patch", "database.request", "management.rcon.request", "management.program.request"]));
expect(manifest.gameClientBridge.queryTemplates.map((query) => query.key)).toEqual(expect.arrayContaining(["scum.player.profile", "scum.squads", "scum.squad-members", "scum.vehicles", "scum.flags", "scum.positions"]));
expect(manifest.gameClientBridge.operationTemplates.map((operation) => operation.key)).toEqual(expect.arrayContaining(["player.fame.set", "player.currency.normal.set", "player.currency.gold.set", "player.notify", "reward.deliver"]));
expect(manifest.gameClientBridge.operationTemplates.map((operation) => operation.key)).not.toContain("player.attribute.855.set");
expect(fs.existsSync(path.join(pluginDir, "schemas/bridge/queries/SCUM_DB_CONTRACT.md"))).toBe(true);
expect(manifest.gameClientBridge.queryTemplates).toEqual([]);
expect(manifest.gameClientBridge.operationTemplates).toEqual([]);
expect(fs.existsSync(path.join(pluginDir, "schemas/bridge/queries/SCUM_DB_CONTRACT.md"))).toBe(false);
});
it("keeps SCUM database-backed live-data gates disabled until current-service evidence exists", () => {
@@ -474,7 +473,7 @@ describe("plugin manifest validation", () => {
snapshots: Array<{ type: string; schemaVersion: string; schemaRef: string }>;
pages: Array<{ pageKey: string; commandTypes?: string[]; snapshotTypes?: string[]; queryTemplateKeys?: string[]; operationKeys?: string[] }>;
};
pages: Array<{ key: string; permissions?: string[] }>;
pages: Array<{ key: string; permissions?: string[]; bridgeActions?: string[] }>;
fileWorkspace?: {
defaultDirectoryKey: string;
directories: Array<{ key: string; label: string; scope: string }>;
@@ -513,16 +512,11 @@ describe("plugin manifest validation", () => {
expect(manifest.gameClientBridge.snapshots.map((snapshot) => snapshot.type)).toEqual(expect.arrayContaining(["companion.health", "online.sessions", "players", "squads", "vehicles", "flags"]));
expect(manifest.gameClientBridge.pages.map((page) => page.pageKey)).toEqual(["players", "squads", "live-map", "gifts"]);
expect(manifest.gameClientBridge.pages.map((page) => page.pageKey)).not.toContain("files-config");
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "players")?.operationKeys).toEqual(expect.arrayContaining([
"player.fame.set",
"player.currency.normal.set",
"player.currency.gold.set",
"player.notify"
]));
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "players")?.operationKeys).not.toContain("player.attribute.855.set");
expect(manifest.gameClientBridge.pages.every((page) => !(page.queryTemplateKeys?.length) && !(page.operationKeys?.length))).toBe(true);
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "workflows")).toBeUndefined();
expect(manifest.pages.map((page) => page.key)).toEqual(["players", "squads", "live-map", "gifts"]);
expect(manifest.pages.map((page) => page.key)).not.toContain("files-config");
expect(manifest.pages.every((page) => !(page.bridgeActions ?? []).includes("remote.access.request"))).toBe(true);
expect(manifest.pages.find((page) => page.key === "players")?.permissions).toEqual(expect.arrayContaining(["server.game-client.read", "server.game-client.command", "server.game-client.maintenance"]));
expect(manifest.fileWorkspace).toBeUndefined();
expect(manifest.runtimeProfiles?.lifecycleProfiles?.find((profile) => profile.key === "scum-client")?.capabilities).not.toContain("remote.run.rcon.command");
@@ -637,7 +631,7 @@ describe("plugin manifest validation", () => {
expect(manifest.gameClientBridge.pages.find((page) => page.pageKey === "live-map")?.snapshotTypes).toEqual(expect.arrayContaining(["players", "vehicles", "flags"]));
});
it("declares typed SCUM.db query templates without browser-visible SQL", () => {
it("keeps SCUM.db query templates absent until current-service evidence exists", () => {
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as {
permissions: string[];
@@ -661,7 +655,7 @@ describe("plugin manifest validation", () => {
pages: Array<{ key: string; permissions?: string[]; bridgeActions?: string[] }>;
runtimeProfiles?: { transportProfiles?: Array<{ key: string; kind: string; targetKey?: string; capabilities: string[] }> };
};
const expectedKeys = ["scum.player.profile", "scum.squads", "scum.squad-members", "scum.vehicles", "scum.flags", "scum.positions"];
const expectedKeys: string[] = [];
const templatesByKey = new Map(manifest.gameClientBridge.queryTemplates.map((template) => [template.key, template]));
expect([...templatesByKey.keys()]).toEqual(expect.arrayContaining(expectedKeys));
expect(manifest.capabilities).toContain("remote.run.db.sqlite.query");
@@ -685,17 +679,17 @@ describe("plugin manifest validation", () => {
const playersPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "players");
const squadsPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "squads");
const mapPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "live-map");
expect(playersPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.player.profile", "scum.positions"]));
expect(squadsPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.squads", "scum.squad-members", "scum.flags"]));
expect(mapPage?.queryTemplateKeys).toEqual(expect.arrayContaining(["scum.vehicles", "scum.flags", "scum.positions"]));
expect(playersPage?.queryTemplateKeys).toBeUndefined();
expect(squadsPage?.queryTemplateKeys).toBeUndefined();
expect(mapPage?.queryTemplateKeys).toBeUndefined();
for (const pageKey of ["players", "squads", "live-map"]) {
const pluginPage = manifest.pages.find((page) => page.key === pageKey);
expect(pluginPage?.permissions).toContain("server.game-client.read");
expect(pluginPage?.bridgeActions).toContain("remote.access.request");
expect(pluginPage?.bridgeActions).not.toContain("remote.access.request");
}
});
it("declares typed SCUM RCON operations without arbitrary command inputs", () => {
it("keeps SCUM RCON operation templates absent until command confirmation is verified", () => {
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as {
gameClientBridge: {
@@ -704,7 +698,7 @@ describe("plugin manifest validation", () => {
};
pages: Array<{ key: string; permissions?: string[] }>;
};
const expectedKeys = ["player.fame.set", "player.currency.normal.set", "player.currency.gold.set", "player.notify", "reward.deliver"];
const expectedKeys: string[] = [];
const operationsByKey = new Map(manifest.gameClientBridge.operationTemplates.map((operation) => [operation.key, operation]));
expect([...operationsByKey.keys()]).toEqual(expect.arrayContaining(expectedKeys));
for (const key of expectedKeys) {
@@ -723,8 +717,8 @@ describe("plugin manifest validation", () => {
}
const playersPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "players");
const giftsPage = manifest.gameClientBridge.pages.find((page) => page.pageKey === "gifts");
expect(playersPage?.operationKeys).toEqual(expect.arrayContaining(["player.fame.set", "player.currency.normal.set", "player.currency.gold.set", "player.notify"]));
expect(giftsPage?.operationKeys).toEqual(expect.arrayContaining(["reward.deliver", "player.notify"]));
expect(playersPage?.operationKeys).toBeUndefined();
expect(giftsPage?.operationKeys).toBeUndefined();
expect(manifest.pages.find((page) => page.key === "players")?.permissions).toContain("server.game-client.command");
expect(manifest.pages.find((page) => page.key === "gifts")?.permissions).toContain("server.game-client.command");
});