Add player moderation workflows and game integration
CI / checks (push) Successful in 7m27s

This commit is contained in:
2026-10-15 21:33:50 -04:00
parent c91d49c298
commit 8b372fa2c1
50 changed files with 4744 additions and 354 deletions
@@ -26,6 +26,7 @@ beforeEach(async () => {
vi.stubEnv('GAME_FILES_ROOT', join(fixture.root, 'libraries'));
vi.stubEnv('PLUTAINER_IMAGE', image);
vi.stubEnv('RCON_PASSWORD', 'test-password');
vi.stubEnv('EC_PUBLIC_URL', 'https://public-controller.example');
const { createHost, createEnrollment, enrollHost, heartbeat } =
await import('../../src/lib/server/hosts/index.js');
@@ -460,3 +461,51 @@ it('injects unique persistent bank credentials only into private runtime files',
)
).toBe(false);
});
it('keeps legacy agents compatible without claiming moderation configuration', async () => {
const job = await queue();
await runPass();
const op = await operationFor(job.deploymentId);
const { getHostOperation } = await import('../../src/lib/server/hosts/index.js');
const payload = getHostOperation(op!.id)!.payload as Record<string, unknown>;
expect(payload.moderation).toBeUndefined();
});
it('injects generation-bound moderation credentials privately on compatible hosts', async () => {
const hosts = await import('../../src/lib/server/hosts/index.js');
hosts.heartbeat(hostId, {
...hosts.getHost(hostId)!.inventory,
capabilities: ['moderation.configure']
});
const job = await queue();
await runPass();
const op = await operationFor(job.deploymentId);
const { nativeInstance } = await import('../../src/lib/server/backends/native.js');
const { moderationCredential } = await import('../../src/lib/server/moderation/credentials.js');
const { recipeForDeployment } = await import('../../src/lib/server/fleet/launch-recipes.js');
const instance = nativeInstance(job.name)!;
const credential = moderationCredential(instance.id, instance.generation);
const payload = hosts.getHostOperation(op!.id)!.payload as {
moderation: { token: string; configPath: string; url: string; generation: number };
files: { path: string }[];
env: Record<string, string>;
};
expect(payload.moderation).toEqual({
token: credential,
configPath: 'configs/electric_cherry_moderation.cfg',
url: 'https://public-controller.example/api/moderation/runtime',
generation: instance.generation
});
expect(payload.files.some((file) => file.path.endsWith('electric_cherry_moderation.cfg'))).toBe(
false
);
expect(payload.env.PLUTAINER_EXTRA_ARGS).toContain('+exec electric_cherry_moderation.cfg');
const { db } = await import('../../src/lib/server/db/index.js');
expect(
db()
.prepare('SELECT count(*) AS n FROM file_blobs WHERE instr(content,?) > 0')
.get(Buffer.from(credential))
).toEqual({ n: 0 });
expect(JSON.stringify(recipeForDeployment(job.deploymentId))).not.toContain(credential);
expect(JSON.stringify(hosts.listHostOperationHistory())).not.toContain(credential);
});