refactor(scum): use runtime capability probes

This commit is contained in:
npc0-hue
2026-07-29 18:34:16 +08:00
parent 03339fb3e8
commit d7465bfd32
26 changed files with 530 additions and 533 deletions
+12 -12
View File
@@ -6,12 +6,12 @@ import { configurationCatalog, validateConfigPatch, validateStatePatch, validate
import { scumMigrationParityFixtures } from "./fixtures/scum-migration-parity.js";
describe("SCUM plugin feature module", () => {
it("owns the versioned configuration and state field catalogs", () => {
expect(configurationCatalog("0.9.700.90357").map((field) => field.key)).toContain("welcome-message");
expect(validateConfigPatch({ version: "0.9.700.90357", reason: "adjust capacity", idempotencyKey: "cfg-1", changes: [{ key: "max-players", value: "129" }] })).toContain("超出允许范围");
expect(validateStatePatch("0.9.700.90357", [{ fieldKey: "skills.running", before: 1, after: 2 }])).toBeNull();
expect(validateStatePatch("unknown", [{ fieldKey: "skills.running", before: 1, after: 2 }])).toContain("未受当前版本支持");
expect(vehicleSpawnCatalog("0.9.700.90357").map((vehicle) => vehicle.code)).toEqual(["BPC_Laika_C", "BPC_WolfsWagen_C"]);
it("owns runtime allowlists without a version gate", () => {
expect(configurationCatalog.map((field) => field.key)).toContain("welcome-message");
expect(validateConfigPatch({ reason: "adjust capacity", idempotencyKey: "cfg-1", changes: [{ key: "max-players", value: "129" }] })).toContain("超出允许范围");
expect(validateStatePatch([{ fieldKey: "skills.running", before: 1, after: 2 }])).toBeNull();
expect(validateStatePatch([{ fieldKey: "unknown", before: 1, after: 2 }])).toContain("白名单");
expect(vehicleSpawnCatalog.map((vehicle) => vehicle.code)).toEqual(["BPC_Laika_C", "BPC_WolfsWagen_C"]);
expect(validateVehicleSpawn({ vehicleCode: "BPC_Laika_C" })).toBeNull();
expect(validateVehicleSpawn({ vehicleCode: "#spawnvehicle BPC_Laika_C" })).toContain("格式无效");
expect(validateVehicleSpawn({ vehicleCode: "BPC_Unknown_C" })).toContain("受控目录");
@@ -26,7 +26,7 @@ describe("SCUM plugin feature module", () => {
expect(migrateConfigurationRecord({ id: "cfg-1", version: "0.9.700.90357", fields: { MaxPlayers: 64 }, observedAt: "2026-07-29T00:00:00Z", hostPath: "C:/secret" })).toMatchObject({ readOnly: true, payload: { fields: { MaxPlayers: "64" } } });
expect(migratePlayerProfileRecord({ player: { id: "p-1", gamePlayerId: "steam-1", displayName: "Mira", updatedAt: "2026-07-29T00:00:00Z" }, sessions: [{ id: "s-1", gamePlayerRecordId: "p-1", startedAt: "2026-07-29T00:00:00Z", networkFingerprint: "never-copy" }], accessAttempts: [{ occurredAt: "2026-07-29T00:01:00Z", outcome: "review", reason: "manual" }] })).toMatchObject({ payload: { sessions: [{ kind: "login" }], risks: [{ summary: "manual" }] } });
expect(migrateGiftGrantRecord({ id: "gift-1", revisionId: "r-1", gamePlayerRecordId: "p-1", status: "unknown", createdAt: "2026-07-29T00:00:00Z" })).toMatchObject({ payload: { status: "unknown" }, readOnly: true });
expect(migrateStatePatchRecord({ id: "patch-1", gamePlayerRecordId: "p-1", gameVersion: "0.9.700.90357", expectedStateVersion: "state-1", safetyWindow: "maintenance", status: "confirmed", createdAt: "2026-07-29T00:00:00Z", changes: [{ fieldKey: "skills.running", before: 1, after: 2 }] })).toMatchObject({ payload: { status: "succeeded" }, readOnly: true });
expect(migrateStatePatchRecord({ id: "patch-1", gamePlayerRecordId: "p-1", expectedStateVersion: "state-1", safetyWindow: "maintenance", status: "confirmed", createdAt: "2026-07-29T00:00:00Z", changes: [{ fieldKey: "skills.running", before: 1, after: 2 }] })).toMatchObject({ payload: { status: "succeeded" }, readOnly: true });
expect(migrateTrajectoryHistoryRecord({ id: "track-1", playerRecordId: "p-1", points: [{ recordedAt: "2026-07-29T00:00:00Z", mapX: 10, mapY: 20 }] })).toMatchObject({ sourceRecordId: "track-1", readOnly: true });
});
@@ -39,11 +39,11 @@ describe("SCUM plugin feature module", () => {
expect(migrateConfigurationRecord({ version: "0.9.700.90357", observedAt: "2026-07-29T00:00:00Z", fields: { hostPath: "/srv/scum" } })).toBeNull();
});
it("enables plugin authority only for one exact server-version feature flag", () => {
const flags = [{ serverInstanceId: "server-1", serverVersion: "0.9.700.90357", feature: "configuration" as const, authority: "plugin" as const }];
expect(migrationStatus(flags, "server-1", "0.9.700.90357", "configuration")).toMatchObject({ authority: "plugin", pluginWritesEnabled: true, readOnlyHistory: true });
expect(migrationStatus(flags, "server-2", "0.9.700.90357", "configuration")).toMatchObject({ authority: "transitional-read-only", pluginWritesEnabled: false });
expect(migrationStatus([...flags, flags[0]], "server-1", "0.9.700.90357", "configuration")).toMatchObject({ authority: "transitional-read-only", pluginWritesEnabled: false });
it("enables plugin authority only for one exact server-feature flag", () => {
const flags = [{ serverInstanceId: "server-1", feature: "configuration" as const, authority: "plugin" as const }];
expect(migrationStatus(flags, "server-1", "configuration")).toMatchObject({ authority: "plugin", pluginWritesEnabled: true, readOnlyHistory: true });
expect(migrationStatus(flags, "server-2", "configuration")).toMatchObject({ authority: "transitional-read-only", pluginWritesEnabled: false });
expect(migrationStatus([...flags, flags[0]], "server-1", "configuration")).toMatchObject({ authority: "transitional-read-only", pluginWritesEnabled: false });
});
it("renders plugin-owned configuration, player, reward, state, and trajectory panels with scoped permissions", () => {