// [HARNESS] Позитивный контроль стенда: эти тесты обязаны быть зелёными всегда. // Если они красные — сломан сам стенд, и красные дефектные сценарии ничего не доказывают. /* eslint-disable @typescript-eslint/no-unsafe-member-access */ import pg from 'pg'; import { describe, expect, it } from 'vitest'; import { api, ctx, describeResponse } from './harness/client.js'; describe('HARNESS: реальный сервер + PostgreSQL 17', () => { it('[HARNESS] сервер отвечает live/ready (ready проверяет БД)', async () => { const live = await api('GET', '/live'); expect(live.status).toBe(200); const ready = await api('GET', '/ready'); expect(ready.status, describeResponse(ready)).toBe(200); expect(ready.body).toEqual({ status: 'ready' }); }); it('[HARNESS] БД: PostgreSQL 17, приложение под ролью без SUPERUSER/BYPASSRLS, мигратор без SUPERUSER', async () => { const client = new pg.Client({ connectionString: ctx().appDatabaseUrl }); await client.connect(); try { const version = await client.query<{ server_version_num: string }>('SHOW server_version_num'); expect(Number(version.rows[0]!.server_version_num)).toBeGreaterThanOrEqual(170000); const roles = await client.query<{ rolname: string; rolsuper: boolean; rolbypassrls: boolean; rolcreaterole: boolean; }>( `SELECT rolname, rolsuper, rolbypassrls, rolcreaterole FROM pg_roles WHERE rolname IN (current_user, 'krona_migrator') ORDER BY rolname`, ); expect(roles.rows).toEqual([ { rolname: 'krona_migrator', rolsuper: false, rolbypassrls: false, rolcreaterole: false }, { rolname: 'krona_staff_app', rolsuper: false, rolbypassrls: false, rolcreaterole: false }, ]); } finally { await client.end(); } }); it('[HARNESS] миграции применены мигратором, app-роль не видит schema_migrations', async () => { const migrator = new pg.Client({ connectionString: ctx().migrationDatabaseUrl }); await migrator.connect(); try { const applied = await migrator.query<{ count: string }>( 'SELECT count(*)::text AS count FROM schema_migrations', ); expect(Number(applied.rows[0]!.count)).toBeGreaterThanOrEqual(11); } finally { await migrator.end(); } const app = new pg.Client({ connectionString: ctx().appDatabaseUrl }); await app.connect(); try { await expect(app.query('SELECT 1 FROM schema_migrations')).rejects.toThrow( /permission denied/, ); } finally { await app.end(); } }); it('[HARNESS] токены: без токена 401, случайный токен 401, manager-токен 200', async () => { expect((await api('GET', '/portal')).status).toBe(401); expect((await api('GET', '/portal', { token: 'x'.repeat(64) })).status).toBe(401); const ok = await api('GET', '/portal', { token: ctx().managerToken }); expect(ok.status, describeResponse(ok)).toBe(200); expect(ok.body.viewer.role).toBe('manager'); }); it('[HARNESS] терминал: отметка сотрудника из импорта принимается (201)', async () => { const { importEmployees, clock, daysAgo } = await import('./harness/fixtures.js'); const [employee] = await importEmployees(1); const response = await clock(employee!.id, 'check_in', daysAgo(1)); expect(response.status, describeResponse(response)).toBe(201); }); // [CTRL] Позитивные контроли безопасности, которые аудит признал рабочими: они // должны оставаться зелёными и доказывают, что сценарии умеют быть зелёными. it('[CTRL] RBAC: терминал не видит портал и не создаёт сотрудников; сотрудник видит только себя', async () => { const { importEmployees, issueEmployeeToken } = await import('./harness/fixtures.js'); const [self, other] = await importEmployees(2); const employeeToken = await issueEmployeeToken(self!.id); const terminalPortal = await api('GET', '/portal', { token: ctx().terminalToken }); const terminalCreate = await api('POST', '/employees', { token: ctx().terminalToken, body: { personnel_number: 'E2E-CTRL', display_name: 'E2E-CTRL' }, }); const own = await api('GET', '/portal', { token: employeeToken }); const rows = (own.body?.employees ?? []) as Array<{ id: string }>; const ids = rows.map((row) => row.id); expect({ terminalPortal: terminalPortal.status, terminalCreate: terminalCreate.status, own: own.status, seesSelf: ids.includes(self!.id), seesOther: ids.includes(other!.id), }).toEqual({ terminalPortal: 403, terminalCreate: 403, own: 200, seesSelf: true, seesOther: false, }); }); it('[CTRL] уволенный сотрудник теряет доступ (401)', async () => { const { importEmployees, issueEmployeeToken } = await import('./harness/fixtures.js'); const [employee] = await importEmployees(1); const employeeToken = await issueEmployeeToken(employee!.id); expect((await api('GET', '/portal', { token: employeeToken })).status).toBe(200); const dismiss = await api('PATCH', `/employees/${employee!.id}`, { token: ctx().managerToken, body: { status: 'dismissed' }, }); expect(dismiss.status, describeResponse(dismiss)).toBe(200); expect((await api('GET', '/portal', { token: employeeToken })).status).toBe(401); }); });