Согласие на cookie относится к браузеру и хранится локально в ключе cookieConsent.
Значения accepted и declined одинаково закрывают баннер при следующих загрузках. Только
accepted разрешает загрузку необязательной аналитики.
Остальные одноразовые окна относятся к аккаунту и синхронизируются с backend:
- ожидание верификации —
verificationNoticeAcknowledgedAtтекущего пользователя; - предложение заполнить профиль —
profileFillPromptAcknowledgedAtтекущего пользователя; - приветствие программы —
welcomeAcknowledgedAtчленства пользователя в программе.
Frontend не записывает эти состояния в localStorage. Загрузка страницы только читает
серверные признаки и не подтверждает показ автоматически. Timestamp появляется после явного
закрытия окна или нажатия его основной кнопки.
- Ожидание верификации показывается, пока аккаунт не верифицирован и уведомление не подтверждено.
- Предложение заполнить профиль показывается только владельцу неполного профиля.
- Приветствие показывается только участнику конкретной программы и только в её detail-разделе.
- Повторный вызов любого подтверждения безопасен и возвращает уже зафиксированное состояние.
- Подтверждения аккаунта работают одинаково на разных устройствах и не переносятся между пользователями; приветствие программы дополнительно изолировано по программе.
POST /auth/users/current/acknowledge-verification-notice/;POST /auth/users/current/acknowledge-profile-fill-prompt/;POST /programs/<program_id>/acknowledge-welcome/.
Дублирующее приветствие на главной странице офиса удалено. Единственный сценарий приветствия остаётся на detail-странице программы.
ProgramDetailResolver преобразует route programId в положительное целое число до
GetProgramUseCase. Для некорректного ID сохраняется прежний fallback new Program()
без HTTP-запроса и без нового окна/маршрута ошибки.
ProgramRepository дополнительно нормализует ID в getOne и acknowledgeWelcome
одним helper: EntityCache всегда получает numeric key. Это исключает разные Map-ключи
"7" при чтении и 7 при инвалидации. Некорректные ID возвращают Observable error,
который существующие use cases преобразуют в Result failure; adapter не вызывается.
Только успешный welcome POST инвалидирует detail-кеш конкретной программы. Другие программы остаются в кеше; TTL 5 минут и архитектура EntityCache не изменены. Failed POST не выставляет timestamp, не закрывает popup и не инвалидирует кеш; pending блокирует повторный клик, после ошибки доступен retry.
Server welcomeAcknowledgedAt остаётся source of truth: после success локальная программа
получает timestamp, popup закрывается; следующий вход выполняет свежий GET и не показывает
приветствие повторно. localStorage/sessionStorage для этого состояния не используются.