Improve operational UX, recovery flows, and action safety

Implement the approved UX review across Fleet, Betas, Library, deployments, and Settings. Add reviewed promotion and reconciliation plans, atomic queued-removal cancellation, recoverable beta drafts and launch inputs, accessible controls, and mobile improvements.

Validated with 473 tests, a clean typecheck, production build, and isolated desktop/mobile browser walkthroughs. Include the review and implementation coverage notes.
This commit is contained in:
2026-09-19 21:34:34 -04:00
parent 940f81e6ca
commit 8ac420fe61
83 changed files with 2574 additions and 1190 deletions
+49
View File
@@ -0,0 +1,49 @@
import { afterEach, beforeEach, expect, it, vi } from 'vitest';
import { newFixture, type Fixture } from '../helpers/fixture.js';
let fixture: Fixture;
beforeEach(async () => {
vi.resetModules();
fixture = await newFixture([]);
vi.stubEnv('KOMODO_ADDRESS', '');
vi.stubEnv('KOMODO_API_KEY', '');
vi.stubEnv('KOMODO_API_SECRET', '');
vi.stubEnv('KOMODO_TARGET_SERVER', '');
vi.stubEnv('RCON_PASSWORD', '');
});
afterEach(async () => { await fixture.cleanup(); vi.unstubAllEnvs(); vi.restoreAllMocks(); });
it('distinguishes missing setup from an unverifiable host volume without probing', async () => {
const probe = vi.spyOn(await import('../../src/lib/server/integrations/netProbe.js'), 'tcpProbe');
const { GET } = await import('../../src/routes/api/system-status/+server.js');
const response = await GET({ url: new URL('http://localhost/api/system-status') });
const body = await response.json();
expect(response.headers.get('cache-control')).toBe('no-store');
expect(body.checks.find((check: { id: string }) => check.id === 'komodo').state).toBe('unconfigured');
expect(body.checks.find((check: { id: string }) => check.id === 'game-files').state).toBe('unverified');
expect(body.readyServers).toBe(0);
expect(probe).not.toHaveBeenCalled();
});
it('never exposes credentials or claims that network reachability validates them', async () => {
vi.stubEnv('KOMODO_ADDRESS', 'https://komodo.example.test');
vi.stubEnv('KOMODO_API_KEY', 'fixture-private-key');
vi.stubEnv('KOMODO_API_SECRET', 'fixture-private-secret');
vi.stubEnv('RCON_PASSWORD', 'fixture-rcon-secret');
vi.spyOn(await import('../../src/lib/server/integrations/netProbe.js'), 'tcpProbe').mockResolvedValue({ label: 'Komodo', host: 'komodo.example.test', port: 443, resolvedIp: '192.0.2.1', outcome: 'connected', elapsedMs: 1 });
const { GET } = await import('../../src/routes/api/system-status/+server.js');
const text = await (await GET({ url: new URL('http://localhost/api/system-status?probe=1') })).text();
for (const secret of ['fixture-private-key', 'fixture-private-secret', 'fixture-rcon-secret']) expect(text).not.toContain(secret);
const connection = JSON.parse(text).checks.find((check: { id: string }) => check.id === 'komodo');
expect(connection.state).toBe('ready');
expect(connection.detail).toContain('does not validate API credentials');
});
it('reports a configured unreachable host as needing attention', async () => {
vi.stubEnv('KOMODO_ADDRESS', 'http://komodo.example.test:9120');
vi.stubEnv('KOMODO_API_KEY', 'key'); vi.stubEnv('KOMODO_API_SECRET', 'secret');
vi.spyOn(await import('../../src/lib/server/integrations/netProbe.js'), 'tcpProbe').mockResolvedValue({ label: 'Komodo', host: 'komodo.example.test', port: 9120, resolvedIp: null, outcome: 'dns-fail', elapsedMs: 1 });
const { GET } = await import('../../src/routes/api/system-status/+server.js');
const body = await (await GET({ url: new URL('http://localhost/api/system-status?probe=1') })).json();
expect(body.checks.find((check: { id: string }) => check.id === 'komodo').state).toBe('attention');
});