Back to About

This document is maintained in Russian.

# Журнал изменений NAP Store

Формат: [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/), нумерация [SemVer](https://semver.org/lang/ru/). До 1.0.0 продукт — MVP для тестирования; 1.0.0 — первый production-релиз. Каждая запись указывает версию ТЗ, которую реализует релиз, и задачи бэклога (`NAP-###`).

## [Не выпущено] — ветка codex/status-timelines

### Статусы с подсказкой «что дальше» (NAP-092)
- Конвертация у автора показана лентой этапов: проверка файла → декодирование → рендеринг → контроль качества → упаковка. Если конвертация остановилась, отмечен этап, на котором это произошло, и сказано, что делать.
- Путь версии приложения: подготовка → модерация → одобрена → в магазине, над подсказкой «Следующий шаг».
- Возврат у покупателя: запрос отправлен → решение → деньги возвращены, с объяснением каждого состояния.
- Один компонент ленты для заказов, конвертации, версий и возвратов: понятен экранным читалкам, проверка доступности без нарушений (82 страницы).

## [Не выпущено] — ветка codex/ops-docs

### Сопровождение сервера (NAP-097)
- Документы для владельца и следующего разработчика: README_DEPLOY.md (точка входа, доступы, переход в боевой режим), ARCHITECTURE.md (что запущено на сервере, сети, каталоги, безопасность), OPERATIONS.md (действия, бэкапы, восстановление по шагам, аварии), COSTS.md (≈ €13/мес сейчас, план роста); в .env.example добавлены настройки публичного сервера и бэкапов.
- Выкладка после принятия PR теперь действительно автоматическая. Её вызывает последний шаг CI на master; прежний запуск по событию «CI завершён» GitHub не срабатывал для автоматически принятых PR. CI на master больше не прерывается новым коммитом посреди выкладки.

### Исправлено
- Бэкап больше не может заполнить диск: архивы файлов хранятся 2 дня, а не 14 (каждый — полная копия всех файлов). Если места мало, архив пропускается с понятной причиной в статусе. Удаление старых дампов выполняется всегда.
- Проверка восстановления бэкапа больше не сообщает ложно «триггеры потеряны», когда журнал аудита пуст: проверка смотрит каталог базы.
## [Не выпущено] — ветка codex/studio-carrier-ramp

### Аудиостудия: плавное изменение несущей (NAP-101)
- В свойствах бинаурального генератора, помимо ритма, можно плавно менять несущую частоту от одного значения к другому, без разрыва фазы. Если конец изменения раньше начала или значение вне допустимого диапазона, подсказка появляется сразу, а не после ошибки сохранения.

## [Не выпущено] — ветка codex/studio-channel-router

### Аудиостудия M2: свои профили вывода (NAP-101)
- В студии появились «Профили вывода». На основе встроенного профиля можно задать, какая шина идёт в какой канал файла и с каким уровнем (в дБ, до +12). По каждому каналу — отключение, переворот полярности и задержка до 100 мс для выравнивания колонок.
- Каждое сохранение создаёт новую версию: прошлые экспорты сохраняют маршрутизацию, с которой были сделаны. Профиль можно убрать в архив, история экспортов при этом остаётся.
- Задержанные каналы при экспорте не обрезаются. Предпросмотр с любого места совпадает с экспортом. Встроенные профили звучат бит в бит как раньше.

### Исправлено
- Шапка сайта иногда не совпадала при загрузке с HTML сервера: вход и корзина успевали загрузиться раньше, чем шапка «оживала». Браузер тогда перерисовывал шапку целиком и писал ошибку в консоль. Теперь шапка показывает вход и корзину после своей загрузки.

## [Не выпущено] — ветка codex/studio-rf64-flac

### Аудиостудия M2: длинные сессии и FLAC (NAP-101)
- Экспорт больше 4 ГБ автоматически записывается в RF64 (WAV без ограничения размера), проверка читает и его.
- Новый формат экспорта FLAC: без потерь, в 3–7 раз меньше WAV, с сохранением раскладки 2.0/3.0/5.1/7.1. Файл принимается, только если распакованные отсчёты совпали с проверенным WAV бит в бит. Для проектов 32-бит float FLAC недоступен (формат его не хранит).

## [Не выпущено] — ветка codex/public-demo-passwords

### Безопасность публичного демо (NAP-097)
- На публичном сервере демо-аккаунты (`*@nap.demo`, включая администратора) больше не принимают документированный пароль `demo-password-1`. У каждого сервера свой секретный пароль, он вычисляется из ключа сервера или задаётся владельцем. Выкладка переводит такие аккаунты на новый пароль и завершает их сессии.
- Пароль выводит команда `python -m app.tools.demo_password` на сервере (docs/vps-deploy.md). Локально, в CI и в превью ничего не меняется.

## [Не выпущено] — ветка codex/arm64-images

### Сервер магазина на Arm (NAP-097)
- Образы backend и web собираются под две архитектуры — x86 (amd64) и Arm (arm64); сервер скачивает свою по тому же digest. Рабочий сервер — Hetzner CAX21 (Ampere, 8 ГБ) в Германии.
- docs/vps-deploy.md: требования к серверу и время выкладки обновлены.

## [Не выпущено] — ветка codex/yookassa

### ЮKassa для покупателей из России (NAP-012)
- Цены в рублях оплачиваются через ЮKassa, остальные валюты — через Stripe; выбор автоматический.
- В каждом платеже — онлайн-чек по 54-ФЗ (e-mail покупателя, позиции, ставка НДС из настроек).
- Уведомления ЮKassa подтверждаются повторным запросом платежа из API и проверкой сети отправителя; возвраты через API.
- Выключено по умолчанию (сервер в Германии, без покупателей из России): включается добавлением RUB в `NAP_CURRENCIES` и ключами ЮKassa. Инструкция — docs/yookassa.md.

## [Не выпущено] — ветка codex/audio-studio-m1

### Аудиостудия, этап M1 (ТЗ аудиоплатформы v2.1; NAP-099, NAP-100)
- В кабинете автора — аудиостудия: проекты на 2/3/6/8 шин, дорожки с waveform, перетаскивание и обрезка клипов, привязка к сетке, отмена/повтор, автосохранение с защитой от одновременной правки.
- Исходники неизменяемы: при загрузке обязательны происхождение и права, SHA-256 подтверждает, что файл не менялся.
- Генераторы ритмов: бинауральный (пара на нейро Л/П, плавное изменение ритма без разрыва фазы) и изохронный (импульсы без щелчков).
- Предпросмотр рендерится на сервере тем же кодом, что и экспорт; показывается реальное число выходов устройства.
- Экспорт WAV в профилях «Наушники 2.0», «NAP 3.0», «Кресло NAP 5.1», «NAP 7.1» с маской каналов; без скрытой нормализации, лимитера и дизеринга; перегрузка — ошибка с указанием канала. Отчёт: пики, true peak, RMS по каналам, SHA-256 и независимая проверка файла.
- Задания экспорта в очереди с повторами, отменой и восстановлением после падения обработчика. Описание и демо-сценарий — docs/audio-studio.md, архитектура и план M2–M6 — docs/architecture/audio-platform.md.

## [Не выпущено] — ветка codex/dev-stand

### Стенд разработки и предпросмотр (NAP-088)
- `ops/dev/stand.sh`: магазин целиком без Docker одной командой (службы, миграции, демо-данные, сборка, запуск, состояние, логи).
- Workflow preview: временная публичная ссылка на любую ветку с демо-данными (Docker-стек на runner + Cloudflare quick tunnel), ссылка приходит комментарием в задачу «Предпросмотр». Описание: docs/dev-stand.md.
## [Не выпущено] — ветка codex/design-v2-stage2

### Редизайн, этап 2 (NAP-093, NAP-095)
- Светлые обложки приложений и товаров в общей палитре; линии несущих — фирменные синий и розовый.
- Каталоги: заголовок с пояснением, компактные фильтры, поиск-«пилюля» с иконкой.
- Метка «Демо» вместо «(демо)» в названиях.
- Страница товара: панель покупки на сером фоне закреплена при прокрутке; характеристики «О товаре», доставка и возврат — раскрываемым блоком.
- Отзывы без оценок: одна строка-приглашение вместо пустой гистограммы. Проверка доступности — 0 нарушений на 78 страницах.

## [Не выпущено] — ветка codex/design-v2

### Редизайн, этап 1 (NAP-089, NAP-090, NAP-091, NAP-092, NAP-096)
- Новая дизайн-система в духе Apple Store: светлая нейтральная палитра, один цвет действия, крупная типографика, фирменный мотив двух несущих L/R. Шрифт Inter хранится в проекте — загрузка с Google убрана.
- Шапка: полупрозрачная, иконка корзины со счётчиком, меню аккаунта вместо одинаковых кнопок.
- Хлебные крошки на страницах приложения, устройства, комплекта и заказа; заголовок страницы с пояснением.
- Заказы: лента этапов «Оформлен → Оплачен → Собирается → Отправлен → Доставлен» и подсказка «Что дальше».
- Главная: новая первая сцена; подвал с колонками ссылок и раскрываемой методикой.
- Принципы дизайна — docs/design.md, итоги UX-аудита — docs/ux/research.md.
## [Не выпущено] — ветка codex/multi-currency

### Цены в долларах и выбор валюты (NAP-012)
- Автор задаёт цену в евро и в долларах; покупатель видит и платит в своей валюте (выбор внизу страницы, иначе по региону браузера: США — доллары, остальные — евро; язык интерфейса цены не меняет). Если цены в его валюте нет — платит в валюте автора.
- Демо-приложения получили цены в долларах. Доли 30/70 считаются в валюте оплаты.

### Выплаты авторам через Stripe Connect (NAP-011)
- В кабинете автора — «Подключить выплаты»: Stripe Connect Express собирает документы, налоговые данные и счёт автора на своей странице; статус «подключены / нужно завершить настройку» виден в разделе «Финансы». Выплаты уходят переводом на счёт автора.

## [Не выпущено] — ветка codex/stripe-world

### Stripe для США и мирового рынка (NAP-010, NAP-012, NAP-020)
- Налоги через Stripe Tax: цены без налога, налог добавляется при оплате — для цифрового по адресу плательщика, для оборудования по адресу доставки; налог проводится отдельно от долей 30/70.
- Один клиент Stripe на пользователя; кабинет «Карты и счета» (Stripe Billing Portal) в профиле.
- Оборудование оплачивается строками «товары» и «доставка»; налог показан в заказе.
- Проверка на настоящем Stripe в тестовом режиме (workflow stripe-sandbox): покупка, подписка, отклонённая карта, возврат, заказ оборудования, портал. Включается секретом STRIPE_TEST_SECRET_KEY.
- Миграция 0010. Инструкция для владельца — docs/stripe.md.
## [Не выпущено] — ветка codex/benchmark-120

### Измерено (NAP-054)
- Конвертация 120-минутного файла на 2 vCPU: 5 мин 9 с (×23,3 быстрее реального времени), пик памяти 291 МБ; результаты в docs/operations.md и docs/qa/benchmark.json. Скрипт замера запускается без PYTHONPATH.
## [Не выпущено] — ветка codex/converter-modes

### Конвертер: режимы 2.0 и 5.1, этап 1 — движок (NAP-063)
- Режим 2.0 для наушников: сдвиг частоты всего трека с разными несущими L/R, разница равна ритму с точностью 0,1 Гц.
- Режим 5.1 для акустической системы NAP: ритм только во фронтальных каналах, центр, сабвуфер и тыл — из загруженных дорожек или генерируются из основного трека; без перекрёстного смешивания.
- Мастер 6 каналов WAV 24 бит и FLAC 5.1, QA по каждому каналу и проверка пилот-тонами. 17 автотестов. Описание: docs/dsp.md.

## [Не выпущено] — ветка codex/vps-autodeploy

### Отдельный сервер и автоматическая выкладка (NAP-087)
- Магазин переезжает на собственный сервер: сбой одного продукта не влияет на napsystem.com.
- GitHub Actions собирает образы backend и web один раз (с кэшем слоёв) и кладёт их в GHCR по digest; на сервере ничего не собирается.
- Выкладка после зелёного CI master — автоматически (по желанию — с подтверждением в окружении production): дамп БД, миграции, переключение, проверка готовности (сборка = коммит, /ru), автоматический возврат предыдущего выпуска при ошибке.
- Управление без SSH: workflow store-ops — состояние, логи, перезапуск после смены настроек, откат, резервная копия.
- Установщик сервера одной командой: автообновления безопасности, firewall, fail2ban, swap, Docker, отдельный пользователь, пароли генерируются на сервере, ключ выкладки ограничен одной программой, HTTPS через Caddy (Let's Encrypt).
- Приёмка на одноразовом Docker-стенде (vps-acceptance) обязательна для автопринятия изменений выкладки. Инструкция: docs/vps-deploy.md.
- Репозиторий переехал в аккаунт владельца: **ma5ter77/napsystem_store**; образы — `ghcr.io/ma5ter77/nap-store-*`. Копия BrothersB/nap-store остаётся архивом; доставка архивов на сервер платформы (deliver-source.yml) удалена.

## [Не выпущено] — ветка codex/release-safety-0.8.0 (черновик #17, обновлён под 0.8.0)

### Безопасность выпуска
- Plan-only по умолчанию, lock deploy/rollback, проверки SHA/окружения/образов, bounded readiness и восстановление предыдущего кода без replay миграций. Первоначальный bootstrap только закрытого demo.
- Проверка синхронности release-документов до CI; push CI учитывает master.

## [Не выпущено] — ветка codex/legal-docs

### Добавлено (NAP-062, NAP-020)
- Правовые документы, редакция 1.0 от 01.11.2026, на русском и английском: Пользовательское соглашение и публичная оферта, Политика обработки персональных данных, Согласие на обработку персональных данных (отдельный документ по 152-ФЗ с 01.09.2025) и Согласие на обработку данных о самочувствии и измерений. Тексты лежат в `docs/legal/`, версии — в `docs/legal/legal.json`. Документы применяются в этой редакции и проходят проверку юриста; в конце каждого есть «Примечания для юриста» с открытыми вопросами.
- Страницы «Правовые документы» (`/legal`) и отдельная страница каждого документа на языке интерфейса; ссылки в подвале сайта. API: `GET /legal`, `GET /legal/{документ}/{ru|en}`.
- Регистрация: два обязательных отдельных флажка без предварительной отметки — принятие соглашения (вместе с политикой) и согласие на обработку персональных данных. Сервер не регистрирует без них и записывает в журнал, какие редакции документов приняты.
- Покупка цифрового контента: у кнопки покупки — принятие соглашения, просьба о немедленном доступе и подтверждение, что после начала доступа право отказа прекращается (требование ЕС для цифрового контента). Оплата заказа оборудования: ссылка на соглашение; продавец товара указан в заказе.
- Согласие на измерения записывается с номером редакции документа. При отзыве согласия все измерения и ответы анкет удаляются сразу — так, как написано в документе.
- Запрос возврата: вариант «Отказ от договора (без объяснения причин)» — причину указывать не нужно (право отказа потребителей ЕС и Сербии); администратор видит пометку отказа.
- Письмо об оплате цифровой покупки повторяет согласие на немедленный доступ и подтверждение утраты права отказа и указывает редакцию Соглашения (подтверждение на долговечном носителе, ст. 8(7) Директивы 2011/83/ЕС).
- Счётчик просмотров страниц приложений больше ничего не хранит в браузере: гость учитывается по одноразовому хешу адреса, браузера и даты внутри вероятностного счётчика (согласие на cookie не требуется).
- Документы прошли независимую проверку (21 замечание: противоречия, обещания, которых нет в продукте, обязательные элементы 152-ФЗ и GDPR); правки внесены, открытые вопросы — в примечаниях для юриста.
- Аудит доступности теперь охватывает и страницы правовых документов: 80 страниц, 0 нарушений.

### Добавлено (выгрузка на сервер, NAP-086)
- `docs/deploy-upload.md` — постоянная инструкция и параметры выгрузки на store.napsystem.com (SSH `napstore@217.114.3.160`, ключ, отпечаток сервера, каталог `/srv/nap-store/incoming`, что разрешено и запрещено) и журнал загрузок.
- `ops/upload-to-store.sh` — скрипт загрузки проверенного исходного архива: проверка входа и отпечатка, выбор коммита (master или `STORE_SHA`), проверка состава на секреты, `git archive`, новая уникальная папка, `scp`, `sha256sum -c`, отчёт владельцу. Если коммит не совпадает с проверенным выпуском, скрипт требует явного подтверждения и честно пишет это в отчёте.
- Пометка «Цены указаны без НДС; НДС начисляется сверху там, где это предусмотрено законом страны покупателя» у цен приложений, в корзине, на странице товара и при оплате. Сам налог пока не рассчитывается (NAP-020).

## [0.8.0] — 2026-11-01 · реализует ТЗ v1.0 (черновик v1.1 на утверждении)

Сводный выпуск: 14 проверенных веток (NAP-021, 023, 024, 025, 027, 028, 040, 042, 043, 044, 045, 047, 050, 051) слиты в одну ветку codex/release-0.8.0, конфликты разрешены, тесты и E2E пройдены на итоговом коде.

### Изменено (публикация, NAP-085)
- План публикации по инструкции владельца от 31.10.2026: магазин — отдельный приватный репозиторий BrothersB/nap-store, адрес https://store.napsystem.com в корне `/`. Скрипт переноса в общий репозиторий удалён; `ops/cohost/` помечен как неактивный пример (сервер, DNS, TLS не трогаются без разрешения владельца), выпуск — от отдельного пользователя, не root.
- `docs/deployment-store.md` переписан под отдельный репозиторий; добавлен `docs/integration-platform.md` — открытые вопросы API/SSO/оплат с платформой.

### Исправлено (доступность, NAP-043)
- Контраст текста статусов поднят до WCAG AA (зелёный, жёлтый, розовый); подписи у списков выбора роли; декоративные обложки скрыты от экранных дикторов; ссылка «Перейти к содержимому»; полоса прогресса сеанса и ползунки анкеты понятны экранным дикторам.

### Добавлено
- `frontend/e2e/a11y.cjs` — аудит WCAG 2.1 AA (axe-core 4.10.3) по 62 страницам всех ролей RU/EN и клавиатурные проверки, шаг в CI; отчёт `docs/qa/a11y-audit.md`.

### Добавлено (NAP-042)
- Плеер: ползунок перемотки (мышь, касание, стрелки клавиатуры), кнопки «−30 с» / «+30 с», «Осталось …», крупные кнопки управления (≥ 48 px).
- Перемотка ставится в очередь событий сеанса — работает офлайн и синхронизируется после восстановления связи; сервер берёт позицию из самого свежего события, поэтому перемотка назад сохраняется, а запоздавшее старое событие её не сдвигает.
- Сеанс засчитывается завершённым, только если прослушано не меньше 80 % программы: перемотка в конец не даёт «завершённого сеанса» (от него зависит право оставить отзыв на платное приложение). Прослушанное время уходит в событиях сеанса.

### Исправлено (NAP-044)
- Несуществующий адрес показывал английскую заглушку Next.js «This page could not be found» без шапки сайта. Теперь — страница «Такой страницы нет» на языке сайта, внутри общего оформления, с переходом в каталог, к устройствам и на главную (HTTP 404).
- Если сервер не ответил, публичные страницы (главная, каталог, карточки, комплекты, «О версии») показывали одно слово «Ошибка». Теперь — «Сервис временно недоступен» с объяснением и кнопками «Обновить страницу» и «На главную».

### Добавлено
- Общий компонент состояний `components/State.tsx` (пусто / ошибка / не найдено / недоступно / нет доступа) — один вид и одни формулировки на серверных и клиентских страницах; через него работают пустые списки, «нужен вход» и «нет доступа».
- Недоступное устройство, платёжный сервис или перевозчик показываются отдельной панелью «недоступно» (это не ошибка пользователя) с повтором и переходом к «Моим устройствам».
- Обработчик непредвиденных сбоев страницы с кнопкой «Попробовать ещё раз».

### Добавлено (NAP-025)
- Своя обложка приложения: «Описание → Обложка». PNG/JPEG/WebP до 10 МБ, не меньше 800×600. Сервер декодирует файл (подделки и повреждённые файлы отклоняются), учитывает поворот камеры, удаляет метаданные (EXIF, геолокация), обрезает по центру до 4:3 и сохраняет WebP 1200×900 — показывается только этот файл.
- Обложка принадлежит версии: меняется в черновике, входит в манифест (размер, SHA-256), замораживается при отправке, проверяется модератором вместе с версией (глубокая проверка целостности), становится обложкой магазина при публикации; новая версия наследует её. Без загруженной — сгенерированная обложка, как раньше.
- Публичный адрес обложки опубликованного приложения с долгим кэшем (`/api/v1/catalog/apps/{slug}/cover?v=…`); черновики не видны посторонним.
- Миграция 0008, зависимость Pillow 11.3.0.

### Добавлено (NAP-047)
- Фотографии товара: в редакторе товара появилась вкладка «Фото» (у поставщика и у модератора). До 8 фото, первое — главное, порядок меняется стрелками, лишнее можно удалить.
  - Каждый файл декодируется и проверяется: PNG, JPEG или WebP, короткая сторона от 600 px, соотношение сторон до 3:1, до 10 МБ. Пропорции сохраняются, файл уменьшается до 1600 px и перекодируется в WebP; метаданные (EXIF, геопозиция, камера) удаляются, прозрачный фон заливается белым.
- Фото проходят модерацию вместе с товаром: поставщик меняет их только в черновике или после отклонения. Модератор видит их при проверке и может изменить на любой карточке; на чужой карточке в продаже нужна причина, поставщику приходит уведомление. Фото черновика видят только поставщик и модераторы.
- Покупатель видит галерею на странице товара (главное фото, стрелки и клавиши ←/→, миниатюры) и главное фото на карточке в каталоге. Товары без фото по-прежнему показывают схематичную иллюстрацию. Фото опубликованных товаров кэшируются навсегда, адрес меняется вместе с файлом.
- Миграция 0009: колонка `products.photos` и тип файла `product_photo`. В проверках готовности товара фото рекомендованы, но не обязательны.

### Добавлено (NAP-021)
- Переходы частот внутри сеанса: профиль может задать кривую разницы частот во времени (например, 10 → 4 Гц за 15 минут). Частота интегрируется в фазу — без скачков и щелчков, результат не зависит от нарезки на блоки. Администратор задаёт кривую при создании версии профиля («секунда = Гц» по строкам).
- QA-отчёт конвертации проверяет переход по всей кривой (окна 4 с в середине участков и после последней точки) и показывает наибольшее отклонение.
- Профили без кривой дают прежний сигнал байт-в-байт; хеши манифестов отправленных версий не меняются. Описание — `docs/dsp.md`.

### Добавлено (NAP-050)
- `ops/loadtest.py` — нагрузочный тест: каталог, покупки с тестовой оплатой, параллельные конвертации; предел по p95 < 500 мс и ошибкам < 1 %. Отчёт `docs/qa/load-test.md`.

### Исправлено
- Каталог приложений и список товаров делали по несколько запросов к базе на каждую карточку (~250 на страницу). Теперь данные загружаются пачкой (6–7 запросов на страницу): ответ каталога 230 → 18 мс, товаров 100 → 16 мс; пропускная способность каталога выросла с ~10 до ~55 запросов/с на один процесс API.
- API запускается в нескольких процессах (`NAP_API_WORKERS`, по умолчанию 2): ~100 запросов/с для каталога на 2 vCPU.

### Добавлено (NAP-023)
- Сохранённые адреса покупателя: адрес, указанный в заказе оборудования, запоминается (без дублей, последние использованные — первыми, до 20 адресов).
- В форме адреса заказа — список сохранённых адресов и кнопка «Доставить сюда»: адрес выбирается одним действием, а правила страны, требование латиницы у перевозчика и страны доставки товаров проверяются заново для этого заказа.
- Профиль → вкладка «Адреса»: список и удаление. API: `GET/POST /me/addresses`, `DELETE /me/addresses/{id}`, `PUT /hardware/orders/{id}/address` принимает `{"address_id": …}`. Новых миграций нет — используется существующая таблица `addresses`.

### Добавлено (NAP-024)
- Запрос возврата цифровой покупки из профиля: «Профиль → Покупки → Запросить возврат», причина обязательна. Пока запрос на рассмотрении, второй отправить нельзя; после отказа можно написать снова.
- Администрирование → вкладка «Возвраты»: очередь запросов с фильтром по статусу, покупатель, сумма оплаты, причина. Администратор одобряет запрос полностью или частично (деньги уходят через платёжного провайдера тем же путём, что и ручной возврат: проводки, доли разработчика, отзыв доступа при полном возврате) или отклоняет его с комментарием.
- Статус запроса и ответ администратора видны в профиле; покупатель получает письма «одобрен» и «отклонён» (шаблоны редактируются в «Контенте сайта»), а после подтверждения провайдером — «Возврат выполнен».
- API: `POST /purchases/{id}/refund-request`, `GET /admin/refund-requests?status=…`, `POST /admin/refund-requests/{id}/decision`; в `/purchases` добавлены `refund_request` и `can_request_refund`. Новых миграций нет: запрос хранится в таблице `refunds` со статусом `requested` / `rejected`.

### Изменено (NAP-040)
- Сгенерированные обложки приложений: вместо случайного оттенка из всего круга — восемь хорошо различимых тонов (океан, бирюза, индиго, янтарь, графит, слива, лес, медь), без тёмно-красных. Свечение ставится в один из углов в зависимости от приложения, поэтому даже одинаковые тона выглядят по-разному. Линии несущих читаются на любом тоне: контраст не ниже 3:1.
- В сетках (главная, каталог, библиотека, кабинет разработчика) у соседних карточек и у карточек в ряду выше тона всегда разные: если тон уже был среди четырёх предыдущих карточек, берётся ближайший свободный. На странице приложения тон постоянный и зависит только от самого приложения.
- E2E проверяет, что в каталоге среди четырёх соседних обложек тона не повторяются.

### Изменено (NAP-028)
- Поиск по приложениям и товарам — полнотекстовый поиск PostgreSQL с русской и английской морфологией вместо поиска по подстроке: «медитации» находит «медитация», «курсы» — «Курс фокуса», «course» и «COURSES» — «Focus Course», «наушников» — наушники.
- Каждое слово запроса должно найтись (И). Слово может совпасть по русской основе, по английской основе или как начало слова («медит»). Смешанные запросы на двух языках работают. Ищется по опубликованным текстам RU/EN, автору и адресу приложения, а у товаров — по бренду и модели.
- Без явной сортировки первыми идут лучшие совпадения: слова в названии весят больше, чем в описании. Выбранная сортировка сохраняется.
- Новых миграций нет. Документы строятся при запросе (`app/services/search.py`); когда каталог вырастет, их можно заменить на хранимую колонку tsvector с GIN-индексом, не меняя API.

### Добавлено (NAP-027)
- Кабинет разработчика → «Аналитика»: выбор приложения и периода (7 / 30 / 90 дней).
  - Воронка: просмотры страницы → получили доступ → начали сеанс → завершили сеанс, с конверсией на каждом шаге. Начатые и завершённые считаются среди тех, кто получил доступ в этом периоде.
  - Сеансы по неделям за 12 недель (начато и завершено) с подсказкой при наведении и таблицей.
  - Возвращаемость: слушатели сгруппированы по неделе первого сеанса, в ячейках — доля начавших сеанс через 1–4 недели.
- Защита малых групп: любое число людей меньше `analytics_min_group` (5) возвращается как «скрыто (< 5)» — в воронке, в неделях и в когортах.
- Просмотры страницы приложения: браузер один раз сообщает о просмотре (`POST /catalog/apps/{slug}/view`, лимит частоты). Сервер учитывает уникальных посетителей в HyperLogLog-счётчиках Redis по дням (≈1 % погрешности, хранятся 400 дней), сами идентификаторы не хранятся. Если Redis недоступен, просмотры показываются как «нет данных», остальное работает.
- API: `GET /developer/analytics/apps/{id}?days=7|30|90`. Новых миграций нет.

### Исправлено
- Тесты сервера удаляют свою временную папку после прогона (раньше каждый прогон оставлял в /tmp около 340 МБ сконвертированного аудио и со временем заполнял диск).

### Изменено (NAP-045)
- Редакторская вычитка словарей интерфейса RU/EN, писем и сообщений об ошибках: 57 правок.
  - Единая терминология: «модерация» / moderation вместо review (чтобы не путать с отзывами), «публичный фрагмент» / public preview, developer/supplier dashboard вместо кальки cabinet, supplier вместо vendor.
  - Русские формы множественного числа: «Оформить 5 заказов», «5 независимых заказов», «21 отдельный заказ». В письме о действии модератора исправлено «с вашим отзыв».
  - Английский: будущее время для будущих событий, естественные формулировки вместо калек (listing вместо card, refund вместо money refund), единое написание cancelled; RU и EN теперь совпадают по смыслу.
- Форматтер сообщений (сайт и сервер) понимает точные значения ICU (`=1 {…}`): число 1 получает свою формулировку, а 21 — обычную форму множественного числа.
- Итоговую вычитку носителями языка можно делать поверх этих правок — все тексты в `frontend/scripts/messages_src.py` и `backend/app/i18n/*.json`, а также в «Контенте сайта».

### Изменено (NAP-051)
- Фронтенд переведён на Next.js 16.4.2 с Next.js 15.5. Версия зафиксирована точно; взят выпуск двухнедельной давности, а не самый свежий 16.4.3.
- Сборка идёт через Turbopack, теперь это сборщик по умолчанию. Перенаправление на язык и запоминание языка перенесены из `middleware.ts` в `proxy.ts` — в Next 16 это соглашение называется так.
- `tsconfig.json` и `next-env.d.ts` обновлены в формате, который Next 16 создаёт сам. React, API и поведение страниц не изменились: проверки i18n и типов, сборка и E2E RU/EN проходят.

## [0.7.1] — 2026-10-31 · реализует ТЗ v1.0 (черновик v1.1 на утверждении)

### Добавлено
- Публикация на поддомене store.napsystem.com рядом с существующим nginx (NAP-085): `ops/cohost/` — override compose (сайт только на 127.0.0.1:3100, общие бэкапы и .env в `/srv/nap-store/shared`), отдельный файл сайта nginx, `deploy-cohost.sh` (выкладка ровно одного коммита в `releases/<sha>`, журнал выпусков), `rollback-cohost.sh`; инструкция `docs/deployment-store.md` и шаблон записи о выпуске `docs/deployments/TEMPLATE.md`; CI проверяет override.
- `ops/cohost/import-into-monorepo.sh` — перенос магазина в BrothersB/nap-trainer (`apps/store`, ветка `codex/store-development`) с сохранением истории, без push и без изменения других веток.

## [0.7.0] — 2026-10-31 · реализует ТЗ v1.0 (черновик v1.1 на утверждении)

### Добавлено
- Управление каталогом для модератора (NAP-084): вкладки «Очередь», «Приложения», «Товары», «Отзывы» с поиском и фильтрами.
  - Товары: создание от имени любого поставщика; правка любой карточки, включая товар в продаже (тексты сразу видны покупателям); публикация, снятие с продажи, мягкое удаление с восстановлением в течение 30 дней.
  - Приложения: правка текстов витрины RU/EN и категории, остановка и возобновление продаж, мягкое удаление (у купивших доступ сохраняется) и восстановление. Цены, звук и программу модератор не меняет.
  - Отзывы и ответы: правка с пометкой «отредактировано модератором» (исходный текст — в журнале), скрытие, удаление, восстановление.
  - Каждое действие требует причины, пишется в «Историю изменений» и журнал аудита; владелец получает уведомление.
- Роль «Редактор контента сайта» (content_editor), «Контент сайта»:
  - правка любого текста интерфейса и шаблонов писем: черновик → публикация, история версий, возврат к встроенному тексту (тексты применяются и на страницах, которые рендерит сервер, и в письмах);
  - редактор категорий RU/EN с отметкой отсутствующих переводов (закрывает NAP-026).
- Миграция 0007: мягкое удаление приложений и товаров, статус отзыва «удалён», пометка правки модератором, таблицы текстов сайта и их версий, роль content_editor.

## [0.6.1] — 2026-10-31 · реализует ТЗ v1.0 (черновик v1.1 на утверждении)

### Исправлено
- «Модератор одобрил — ничего не произошло» (NAP-083). Одобрение работало, но приложение не попадало в магазин: версия ждала, пока автор задаст цену и нажмёт «Опубликовать», и этого не было видно ни модератору, ни автору. Теперь у версии есть «Публиковать сразу после одобрения» (по умолчанию включено): при заданной цене одобрение сразу публикует приложение; если цены нет — публикация происходит в момент сохранения цены. Модератор после решения видит, что именно произошло: «одобрена и опубликована» со ссылкой в магазин или «появится, как только автор задаст цену». Автор получает письмо «Приложение опубликовано» или инструкцию, что сделать.
- В очереди модерации приложения показывались техническим адресом (`ocean-mvwq7mku`) — при нескольких похожих приложениях легко было одобрить не то. Теперь — название, автор, адрес и что будет после одобрения.
- Миграция 0006 (`app_versions.auto_release`).

## [0.6.0] — 2026-10-31 · реализует ТЗ v1.0 (черновик v1.1 на утверждении)

### Добавлено
- Закрытое S3-хранилище (NAP-004): профиль compose `s3` со встроенным SeaweedFS 4.45 (порт наружу не открыт, анонимный доступ выключен) или любой внешний S3. Бакет создаётся при первом запуске; бакет с публичной политикой не принимается. Команды `python -m app.tools.storage migrate` (перенос файлов с тома под теми же ключами, со сверкой размера и SHA-256, повторный запуск ничего не копирует) и `check` (запись, чтение, Range, хэш, подписанная ссылка, отказ анонимному запросу). Ежедневный бэкап архивирует данные встроенного S3. `/ready` проверяет доступность хранилища. Глубокая проверка целостности опубликованных версий читает файлы и из бакета.
- Товары поставщика (NAP-022): «Кабинет поставщика → Товары» — карточка, варианты (SKU) с ценой, габаритами, страной происхождения, кодом HS и аккумулятором, характеристики, тексты RU/EN с комплектацией, список готовности, отправка на модерацию, история решений. Модератор видит очередь товаров, одобряет (товар и тексты сразу в каталоге) или отклоняет с обязательным комментарием; поставщик получает уведомление. У опубликованного товара цена и включение вариантов меняются сразу, карточка — через «Снять с продажи и изменить».
- Инструкция «Как поставщику выставить товар на продажу» (`docs/guide.ru.md`).

### Изменено
- MinIO заменён на SeaweedFS: MinIO Community в архиве с апреля 2026, образы удалены с Docker Hub в сентябре 2026.

## [0.5.0] — 2026-10-31 · реализует ТЗ v1.0 (черновик v1.1 на утверждении)

### Добавлено
- Отправка писем (NAP-007): каждое уведомление — одно письмо на языке получателя (текст + HTML), транспорт `log` / `file` (.eml) / `smtp` (STARTTLS/SSL); повтор при сбое с экспоненциальной паузой 30 с … 1 ч через outbox (`next_attempt_at`, миграция 0005); статус доставки у уведомления; метрики `nap_emails_failed`, `nap_outbox_stuck`.
- Ежедневный бэкап (NAP-006): сервис `backup` в compose — дамп, восстановление во временную базу со сверкой, архив хранилища, срок хранения; статус в `/metrics` (`nap_backup_ok`, `nap_backup_age_seconds`) и в «Администрирование → Эксплуатация».
- Мониторинг (NAP-005): профиль compose `monitoring` (Prometheus + Alertmanager), 10 правил оповещений (API, 5xx, конвертации, вебхуки, outbox, письма, бэкап), доставка оповещений письмом; CI проверяет конфигурации.
- Черновик ТЗ v1.1 (NAP-060): решения 0.3.0–0.4.x, новый раздел «Оценки и отзывы», критерии приёмки 39–52, кандидаты в ТЗ 2.0; на странице «О версии» отмечен как черновик.
- Инструкция «Как одобрить приложение другого разработчика и выпустить его в магазин» (`docs/guide.ru.md`).

## [0.4.0] — 2026-10-31 · реализует ТЗ v1.0

### Исправлено
- «Отправить на модерацию» и решение модератора — казалось, что «ничего не происходит» (NAP-082): запросы выполнялись, но результат был виден только по маленькому значку. Теперь в редакторе приложения на всех вкладках есть баннер «Следующий шаг» (что заполнить, что отправить, сколько ждать, что делать после одобрения или отклонения); на вкладке «Версии и публикация» — чек-лист готовности со ссылками на вкладки, кнопка отправки активна, когда всё обязательное готово; после сохранения, отправки, публикации, отзыва версии — сообщение о результате; в «Описании» — подсказка о несохранённых изменениях (в т. ч. неподтверждённых правах). Модератор после решения видит подтверждение и кнопку «Следующая в очереди».

### Добавлено
- Оценки и отзывы на товары (NAP-079): только после доставки заказа с товаром (метка «Покупка подтверждена», вариант товара), продавец не оценивает свои товары и отвечает из кабинета поставщика (вкладка «Отзывы»), общая очередь модерации; рейтинг на карточках, фильтр «4 и выше» и сортировка по оценке в каталоге устройств; демо-отзывы. Модель отзывов общая для приложений и товаров (миграция 0004).

## [0.3.0] — 2026-10-31 · реализует ТЗ v1.0

### Добавлено
- Оценки и отзывы приложений (NAP-065): 1–5 звёзд, заголовок и текст, привязка к версии и языку; средняя оценка с 5 оценок, распределение по звёздам, средняя по текущей версии; сортировка и фильтры, «Полезно», жалобы. Оценивать могут только пользователи с доступом, для платных — после завершённого сеанса; разработчик не оценивает свои приложения и не может менять, скрывать или удалять отзывы — только публично отвечать (вкладка «Отзывы» в кабинете с фильтрами и динамикой по месяцам). Ссылки, контакты, запрещённые слова и медицинские обещания в ответах уходят на модерацию; очередь «Отзывы и жалобы» у модератора. Рейтинг на карточках, фильтр «4 и выше» и сортировка по оценке в каталоге; демо-оценки.
- Компактная шапка на телефоне (NAP-041): одна строка, кнопка «Меню» с управлением с клавиатуры (Esc закрывает, фокус возвращается).
- Ограничение частоты запросов (NAP-052): общий лимит и отдельные лимиты на ссылки загрузки, части файлов, оплаты, вебхуки, отзывы и конвертации; ответ 429 с текстом на RU/EN и `Retry-After`; настройка `NAP_RATE_LIMITS`. Загрузка частями сама ждёт и повторяет при 429.
- CI (NAP-003): `.github/workflows/ci.yml` — тесты сервера с PostgreSQL/Redis и проверкой миграций, проверки и сборка фронтенда, E2E RU/EN, сборка и запуск Docker Compose, итоговая проверка `ci-ok` для защиты ветки.
- Профиль конвертера «Гамма (40 Гц)», `gamma-40-v1` (NAP-080, параметры заказчика): чистые синусоиды 200 Гц слева и 240 Гц справа, каналы не смешиваются, плавный вход/выход 3 с; QA подтверждает 40 ± 0,1 Гц. Добавляется и в уже развёрнутые демо-базы. Ожидает подписи методистов (NAP-061).
- Контрольная сумма большого файла считается в браузере по частям (hash-wasm), файл целиком в память не читается (остаток NAP-069).

### Исправлено (проверка всех страниц веб-версии: 192 страницы, RU/EN, компьютер и телефон)
- Корзина: товар, которого нет в нужном количестве, подсвечивается, оформление блокируется с понятной причиной (раньше — ошибка после нажатия); появилась кнопка «Убрать», количество применяется по Enter.
- Горизонтальная прокрутка страниц на телефоне: карточка комплекта, редактор приложения, заказ поставщика, профили в админке.
- Подпись отчёта контроля качества была на английском в русском интерфейсе.
- Конвертация больше не отвечает 500, если брокер очередей недоступен: задание остаётся в очереди и отправляется повторно автоматически.
- Внешние ключи `apps` на версию, обложку, превью и комплект отсутствовали в базе (миграция 0003 их добавляет).
- Итог приёмки на странице «О версии» показывался по-английски в русском интерфейсе.

## [0.2.3] — 2026-10-31 · реализует ТЗ v1.0

### Исправлено
- Загрузка аудио больше 10 МБ обрывалась: Next.js пропускает через свой прокси только первые 10 МБ тела запроса, сервер получал обрезанный файл и отвечал ошибкой — трек не появлялся, «Программа» и отправка на модерацию не работали (NAP-069). Файл теперь загружается частями по 8 МБ (`Content-Range`) с докачкой: часть, пришедшая не по порядку, получает 409 с текущим смещением, и браузер продолжает с него. Проверено на MP3 60 минут (86 МБ) через веб-интерфейс.
- Конвертация запускается сама сразу после загрузки с выбранным профилем (галочку можно снять); раньше шаг «Конвертировать» легко было пропустить.
- Первый готовый трек автоматически становится сеансом 1 пустой программы черновика с названием приложения: для одной медитации шаг «Программа» не нужен, его можно только поправить.
- Docker: файл расписания Celery beat перенесён в `var/` — образ работает под непривилегированным пользователем, и `/app` для него недоступен на запись; рабочие файлы beat больше не попадают в репозиторий.
- Вкладка «Аудио и конвертер» разбита на шаги (1. профиль, 2. загрузка, 3. задания), «Программа» объясняет, зачем она нужна.

### Добавлено
- Тест сервера на загрузку частями, докачку и автозаполнение программы; E2E загружает 60-секундный WAV (11 МБ, две части) через прокси Next.js.

## [0.2.2] — 2026-10-31 · реализует ТЗ v1.0

### Исправлено
- «Программа»: сохранение сеанса без выбранного трека давало «Внутренняя ошибка» (500) — пустой идентификатор конвертации не проверялся на сервере (NAP-068). Теперь сервер отвечает 422 с указанием поля (`sessions.N.track`, также для ключа и названий), а форма не отправляет программу, пока у каждого сеанса не выбран трек, и подсвечивает пустой трек.
- Если готовых треков ещё нет, вкладка «Программа» объясняет, что трек появляется после загрузки аудио и конвертации, и ведёт на вкладку «Аудио и конвертер».
- Блок ошибки называет поле программы понятно: «Сеанс 2: трек».

### Добавлено
- Тест сервера на некорректные сеансы программы (всегда 422, не 500) и шаг E2E с сеансом без трека.

## [0.2.1] — 2026-10-31 · реализует ТЗ v1.0

### Исправлено
- «Новое приложение»: адрес с подчёркиванием давал общую ошибку «Проверьте введённые данные» без указания поля (NAP-067). Причина — шаблон `pattern` адреса не компилировался с флагом `v` в современных браузерах (неэкранированный дефис в классе символов), и проверка в браузере молча отключалась.
- Адрес нормализуется при вводе: заглавные буквы → строчные, подчёркивание и пробелы → дефис; недопустимые символы останавливаются в браузере до отправки.
- Блок ошибки называет поле для любых ошибок проверки (`details.field` и `details.fields` в обоих форматах); поле с ошибкой подсвечивается.
- Подсказка к адресу на RU/EN уточнена; поля формы больше не растягиваются по высоте при длинной подсказке.

### Добавлено
- `npm run check-patterns`: все `pattern` в интерфейсе проверяются компиляцией с флагом `v`.
- E2E: сценарий с нелатинским адресом (запрос не отправляется) и адресом с подчёркиванием и заглавными буквами.

## [0.2.0] — 2026-10-31 · реализует ТЗ v1.0

### Добавлено
- Версионность ТЗ (`docs/spec/`), описание проекта с версией документа (`docs/PROJECT.md`), этот журнал и `release.json` как единый источник версий.
- Страница продукта «О версии» (`/ru/about`, `/en/about`): версия продукта и ТЗ, покрытие разделов ТЗ, итоги приёмки, история релизов, ссылка на бэклог; версия в подвале каждой страницы.
- `GET /api/v1/version` и `GET /api/v1/about/documents/{name}` (ТЗ, описание проекта, журнал изменений) — то же для внешних систем.
- Бэклог доработок с общей базой задач (NAP-009).

## [0.1.1] — 2026-10-31 · реализует ТЗ v1.0

### Исправлено
- Docker Compose: несуществующий тег образа `minio/mc`; demo-стенд работает без MinIO на закрытом томе (NAP-008).
- Next.js в контейнере обращался к API по `127.0.0.1` (адрес зашивается при сборке) — теперь `http://api:8000`.
- Сборка образа фронтенда падала без папки `public`; установка uv в образ бэкенда через pip с точной версией.

### Добавлено
- `ops/deploy-vps.sh`: развёртывание тестового стенда на Ubuntu-VPS одной командой (Docker + Caddy, HTTPS при наличии домена).

## [0.1.0] — 2026-10-31 · реализует ТЗ v1.0

Первая поставка MVP по ТЗ v1.0: приложения и версии с модерацией, настоящий бинауральный конвертер (FFmpeg + NumPy, QA-отчёт), каталог RU/EN, покупки и подписки (Mock + Stripe test), распределение 30/70 с неизменяемым журналом, выплаты и возвраты, магазин оборудования (BOM, склад с резервами, разделение заказов по продавцам, международная доставка Mock/ручная/EasyPost test, посылки, tracking, возвраты), кабинеты разработчика, поставщика, модератора и администратора, сеансы с симулятором кресла и веб-проигрывателем, анкеты и измерения с согласием, TypeScript SDK, OpenAPI, Docker Compose.

Приёмка: 35 критериев passed, 0 failed, 3 not run (Docker Compose в среде без Docker Hub; live-sandbox Stripe и EasyPost без ключей). Подробно — `docs/acceptance-report.md`.