# Фаза 38. Сессия ## Зависимости - [Фаза 1](01-manager-shell.md) - [Фаза 2](02-school-worker.md) - [Фаза 28](28-screen-tests.md) ## Зачем В клиент не пускает без пароля альфы и имени. Имя запоминается. Сокет открывается только после сессии. Школы пока общие — хозяин в фазе 39. ## Задачи - [x] `HSchool:AlphaPassword` в конфиге; пустая строка — процесс не стартует. В `appsettings.json` заглушка для локальной игры; headless AppHost задаёт тестовый пароль окружением - [x] `POST /api/session` `{ password, userName }`: неверный пароль — `401` `bad-password`; кривое имя — `400` `invalid-name` (те же правила, что у школы); имя с живым сокетом — `409` `name-online`. Успех ставит HttpOnly-куку и при первом разе пишет имя в `saves/users.json` (занятость без учёта регистра) - [x] `GET /api/session` — текущее имя или `401`. `DELETE /api/session` снимает куку - [x] Все игровые HTTP без куки — `401`. Живут без неё: `/health` и три ручки сессии - [x] WebSocket без куки не шлёт Welcome, закрывается. Hello по-прежнему версия + локаль - [x] Клиент: шаг пароля, шаг имени; при живой куке оба пропускаются. Сокет — после сессии. Кнопка выхода на меню - [x] Хостовые тесты логинятся в общем месте (`ResetAsync` или рядом), не в каждом факте - [x] `docs/protocol.md` — HTTP сессии в том же коммите. Раскладку сокета и версию не трогать ## Тесты, без которых фаза не закрыта - [x] Без сессии `GET /api/schools` — `401`; после `POST /api/session` — `200` - [x] Верный пароль и новое имя пишут `users.json`; повтор с тем же именем (другой регистр) — тот же человек, не вторая запись - [x] Пока сокет имени жив, второй `POST /api/session` с ним — `409` `name-online` - [x] Сокет без куки закрывается, Welcome не приходит - [x] Клиентский тест: без куки виден ввод пароля, не сетка школ ## Критерий готовности - Открыть клиент, ввести пароль и имя, попасть в меню; обновить страницу — снова меню, без формы - `dotnet test` и `npm test` / `build` проходят ## Стоп Не делить школы на мои/чужие. Не менять `MaxSchools`. Не трогать таблицу скоростей.