Gate SCUM typed RCON catalog declarations

This commit is contained in:
npc0-hue
2026-08-13 10:47:42 +08:00
parent 25a823f298
commit 396a9d25f6
6 changed files with 38 additions and 6 deletions
+25
View File
@@ -305,6 +305,19 @@ describe("plugin manifest validation", () => {
expect(JSON.stringify(manifest.scumLiveData).toLowerCase()).not.toMatch(/select\s+.+from|sqlite:\/\/|mysql:\/\/|password|credential|socket|hostpath/);
});
it("omits unverified SCUM typed RCON templates and gift catalogs", () => {
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as GamePluginManifest & { scumLiveData: SCUMLiveDataManifestDeclaration };
const liveData = manifest.scumLiveData;
const gates = new Map(liveData.capabilityGates.map((gate) => [gate.capability, gate]));
expect(liveData.typedRconTemplates ?? []).toEqual([]);
expect(liveData.giftCatalogs ?? []).toEqual([]);
expect(gates.get("economy-command.write")).toMatchObject({ gate: "disabled", evidenceStatus: "missing" });
expect(gates.get("gift-command.write")).toMatchObject({ gate: "disabled", evidenceStatus: "missing" });
expect((manifest.assetFiles ?? []).map((file) => file.path).filter((assetPath) => /assets\/scum-live\/(?:rcon|gifts)\//.test(assetPath))).toEqual([]);
expect(JSON.stringify(liveData).toLowerCase()).not.toMatch(/#setcurrency|#setfame|sendchat|commandtext|rawcommand|starter-pack|bandage|water-bottle|improvised-spear/);
});
it("packages SCUM live read query assets with exact bounded result schemas", () => {
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as GamePluginManifest & { scumLiveData: SCUMLiveDataManifestDeclaration };
@@ -531,6 +544,18 @@ describe("plugin manifest validation", () => {
expect(errors.some((error) => error.includes("transportTemplateKeys") && error.includes("missing-template"))).toBe(true);
});
it("rejects SCUM typed RCON templates without conclusive confirmation schemas", () => {
const errors = validateTemporaryScumCompanionManifest((manifest, fixtureDir) => {
const assetPath = "assets/scum-live/rcon/unverified-gift.json";
manifest.assetFiles = [...(manifest.assetFiles ?? []), { path: assetPath, mode: 384 }];
writeFixtureJSON(fixtureDir, assetPath, { packaged: true });
writeFixtureJSON(fixtureDir, "schemas/scum-live/unverified-gift.payload.schema.json", bridgeObjectSchema({ playerId: { type: "string", minLength: 1, maxLength: 96 } }, ["playerId"]));
writeFixtureJSON(fixtureDir, "schemas/scum-live/unverified-gift.result.schema.json", bridgeObjectSchema({ outcome: { enum: ["succeeded", "failed", "unknown"] } }, ["outcome"]));
manifest.scumLiveData.typedRconTemplates = [{ key: "unverified-gift", adapterVersion: "scum-live-data-v1", assetPath, digest: sha256FixtureDigest(fixtureDir, assetPath), capability: "gift-command.write", requiredSchemaFingerprint: currentSCUMSchemaFingerprint, transportKey: "scum-management", targetKey: "scum-management", permission: "server.game-client.command", payloadSchemaRef: "schemas/scum-live/unverified-gift.payload.schema.json", resultSchemaRef: "schemas/scum-live/unverified-gift.result.schema.json", timeoutMs: 5000, maxPayloadBytes: 2048 }];
});
expect(errors.some((error) => error.includes("confirmationSchemaRef"))).toBe(true);
});
it("declares SCUM install/update and start lifecycle through plugin assets", () => {
const pluginDir = path.join(pluginsRoot, "examples/scum-server-plugin");
const manifest = JSON.parse(fs.readFileSync(path.join(pluginDir, "manifest.json"), "utf8")) as any;