Complete platform management workflows

This commit is contained in:
npc0-hue
2026-07-14 16:39:37 +08:00
parent 7e05d0a4e7
commit 4f33f761a3
106 changed files with 11313 additions and 460 deletions
@@ -0,0 +1,38 @@
{
"$schema": "../../manifests/game-plugin.manifest.schema.json",
"id": "game.unsafe-runtime",
"name": "Unsafe Runtime Fixture",
"description": "Fixture with unsafe runtime profile values.",
"version": "0.1.0",
"kind": "game-plugin",
"server": {
"type": "unsafe-runtime",
"displayName": "Unsafe Runtime Fixture",
"createFormSchema": "create-form.valid.json"
},
"capabilities": ["process.start", "process.stop", "logs.read"],
"permissions": ["server.read", "server.lifecycle", "server.logs.read"],
"runtimeProfiles": {
"discovery": [
{"key": "leaky", "kind": "command.version", "targetKey": "java", "expected": "password=super-secret"}
],
"installPlans": [
{"key": "unsafe-install", "title": "bash -c installer", "steps": [{"type": "manual", "targetKey": "manual"}]}
],
"clientManagers": [
{
"key": "unsafe-client",
"repository": {"url": "https://github.com/F88888/scum_client.git", "revisionPolicy": "branch", "branch": "main"},
"supportedTargets": [{"os": "windows", "arch": "amd64"}],
"build": {"system": "go", "workspaceRef": "scum_client", "entryRef": "main.go"},
"configTemplates": [{"key": "bad", "templateRef": "/Users/tasia/client.json", "outputRef": "config.json"}],
"outputArtifacts": ["scum_client.exe"]
}
]
},
"actions": {
"install": "actions/install.json",
"start": "actions/start.json",
"stop": "actions/stop.json"
}
}
+105
View File
@@ -5,13 +5,19 @@ import {
canRequestBridgeAction,
createAIInvocationRequest,
createArtifactOpenRequest,
createClientManagerRequest,
createBridgeExecutionRequest,
createLifecycleDispatchRequest,
createBridgeRequest,
createDependencyActionRequest,
createLogBackfillRequest,
createRemoteAccessRequest,
createRunDistributionRequest,
hasPluginPermission,
parseArtifactReference,
parseBridgeExecutionResponse,
parseAIInvocationResponse,
type GamePluginManifest,
type PluginBridgeContext
} from "../sdk/index.js";
import { validateManifestFile } from "../scripts/validate-manifest.js";
@@ -25,6 +31,10 @@ describe("plugin manifest validation", () => {
expect(validateManifestFile("examples/scum-server-plugin/manifest.json")).toEqual([]);
});
it("accepts the Minecraft server plugin manifest", () => {
expect(validateManifestFile("examples/minecraft-server-plugin/manifest.json")).toEqual([]);
});
it("rejects a manifest with an invalid create form schema", () => {
const errors = validateManifestFile("tests/fixtures/invalid-create-form-manifest.json");
@@ -37,6 +47,14 @@ describe("plugin manifest validation", () => {
expect(errors.some((error) => error.includes("direct run access"))).toBe(true);
expect(errors.some((error) => error.includes("raw credential or AI/provider key"))).toBe(true);
});
it("rejects unsafe runtime profile values", () => {
const errors = validateManifestFile("tests/fixtures/unsafe-runtime-profile-manifest.json");
expect(errors.some((error) => error.includes("raw credential or AI/provider key"))).toBe(true);
expect(errors.some((error) => error.includes("raw host path"))).toBe(true);
expect(errors.some((error) => error.includes("arbitrary shell"))).toBe(true);
});
});
describe("plugin SDK", () => {
@@ -266,4 +284,91 @@ describe("plugin SDK", () => {
expect(JSON.stringify(request)).not.toContain("Bearer ");
expect(JSON.stringify(request)).not.toContain("sk-");
});
it("builds remote access request envelopes without direct transport secrets", () => {
const context: PluginBridgeContext = {
pluginId: "game.minecraft",
routeKey: "rcon",
serverInstanceId: "server-1",
permissions: ["server.remote.access"]
};
expect(canRequestBridgeAction(context, "remote.access.request")).toBe(true);
const request = createRemoteAccessRequest({
requestId: "remote-rcon-1",
context,
capability: "remote.run.rcon.command",
targetKey: "rcon/command",
inputRef: "input://server-1/rcon/command/1",
idempotencyKey: "idem-remote-rcon"
});
expect(request).toEqual({
requestId: "remote-rcon-1",
pluginId: "game.minecraft",
routeKey: "rcon",
serverInstanceId: "server-1",
action: "remote.access.request",
aiPurpose: undefined,
payload: {
capability: "remote.run.rcon.command",
targetKey: "rcon/command",
inputRef: "input://server-1/rcon/command/1",
idempotencyKey: "idem-remote-rcon"
}
});
expect(JSON.stringify(request)).not.toContain("tcp://");
expect(JSON.stringify(request)).not.toContain("password=");
expect(JSON.stringify(request)).not.toContain("/Users/");
});
it("types runtime profile declarations without raw credentials", () => {
const manifest: GamePluginManifest = {
id: "game.runtime",
name: "Runtime Fixture",
version: "0.1.0",
kind: "game-plugin",
server: { type: "runtime", displayName: "Runtime Fixture", createFormSchema: "schemas/create-form.schema.json" },
capabilities: ["process.start", "process.stop", "logs.read"],
permissions: ["server.read", "server.lifecycle", "server.logs.read"],
runtimeProfiles: {
discovery: [{ key: "java", kind: "command.version", targetKey: "java", required: true }],
dependencyProbes: [{ key: "java-21", kind: "java.version", targetKey: "java", minimumVersion: "21" }],
logSources: [{ key: "console", kind: "process.stdout", streamKey: "console", cursorKind: "sequence" }],
transportProfiles: [{ key: "files", kind: "file", capabilities: ["files.read"] }]
}
};
expect(manifest.runtimeProfiles?.discovery?.[0].targetKey).toBe("java");
expect(JSON.stringify(manifest)).not.toContain("password=");
});
it("builds run distribution, dependency, log backfill, and client-manager envelopes", () => {
const context: PluginBridgeContext = {
pluginId: "game.scum",
routeKey: "remote",
serverInstanceId: "server-1",
permissions: ["server.run.distribution", "server.dependencies.manage", "server.logs.read", "server.client-manager.manage"]
};
expect(canRequestBridgeAction(context, "run.distribution.request")).toBe(true);
expect(createRunDistributionRequest({ requestId: "run-gen-1", context, operation: "generate", targetOS: "windows", targetArch: "amd64", idempotencyKey: "idem-run" })).toMatchObject({
action: "run.distribution.request",
payload: { operation: "generate", targetOS: "windows", targetArch: "amd64", idempotencyKey: "idem-run" }
});
expect(createDependencyActionRequest({ requestId: "dep-1", context, operation: "check", probeKey: "steamcmd", idempotencyKey: "idem-dep" })).toMatchObject({
action: "dependencies.request",
payload: { operation: "check", probeKey: "steamcmd" }
});
expect(createLogBackfillRequest({ requestId: "logs-1", context, sourceKey: "chat-log", limit: 500, idempotencyKey: "idem-logs" })).toMatchObject({
action: "logs.backfill.request",
payload: { sourceKey: "chat-log", limit: "500" }
});
expect(createClientManagerRequest({ requestId: "client-1", context, operation: "generate", profileKey: "scum-client-manager", targetOS: "windows", targetArch: "amd64", idempotencyKey: "idem-client" })).toMatchObject({
action: "client-manager.request",
payload: { operation: "generate", profileKey: "scum-client-manager" }
});
expect(JSON.stringify(createClientManagerRequest({ requestId: "client-2", context, operation: "reset-key", profileKey: "scum-client-manager", idempotencyKey: "idem-reset" }))).not.toContain("secret");
});
});