TL;DR: мы держим ваши данные на вашем устройстве. Сервер не имеет доступа к вашей библиотеке, заметкам, прогрессу, SRS-карточкам. Единственное что сервер видит — текст, который вы отправляете в TTS, Gemini-перевод или транслитерацию (для произведения этих stateless- услуг). Никакой аналитики, трекеров, рекламы.
#Что хранится на вашем устройстве
Когда localMode активен (по умолчанию с v3.0.0), всё ниже хранится
локально в браузере через Origin Private File System (OPFS):
- Все ваши тексты + предложения + переводы.
- Заметки к предложениям.
- SRS-карточки и прогресс изучения.
- История сессий, события воспроизведения.
- Настройки UI (тема, язык, выбор голоса TTS).
Подробности о том где физически живут данные — в
OPFS_USER_GUIDE.md.
#Что отправляется на сервер
Сервер (Hetzner CX23, Falkenstein, Германия — EU) держит только stateless-сервисы. Никаких пользова- тельских данных не сохраняется. Перечень того, что отправляется:
#При синтезе TTS
- Текст предложения (1-200 слов на иврите).
- Параметры голоса (язык, voice name, speed, pitch).
- → Уходит в Google Cloud Text-to-Speech.
- → Возвращённое аудио кэшируется на сервере по hash'у текста+параметров, чтобы повторное воспроизведение не тратило вашу TTS-квоту.
#При сборке таблицы
- Исходный текст (1-2000 слов на иврите).
- Параметры (язык целевой, профиль транслитерации).
- → Уходит в Gemini API (Google).
- → Результат не сохраняется на сервере, а возвращается клиенту.
#При транслитерации
- Hebrew с никудом (для конвертации в латиницу или русские фонетические знаки).
- → Обрабатывается локально на сервере (deterministic, нет внешнего API).
- → Не сохраняется.
#При DOCX-экспорте
- Содержимое одного текста (предложения + перевод).
- → Стримится обратно как файл, не сохраняется.
#При prefetch'е аудио (batch TTS)
- Список предложений + параметры голоса.
- → Аналогично one-shot TTS, кэш по hash'у.
#Что НЕ собирается и не отправляется
- Никакой телеметрии о вас как пользователе.
- Никаких cookies для трекинга (только функциональные настройки в localStorage).
- Никакой передачи ваших библиотек, заметок, прогресса третьим сторонам.
- Никаких рекламных идентификаторов.
- Никаких аналитических SDK (Google Analytics, Mixpanel, etc.).
#Обратная связь и feedback-модалка
Когда вы используете кнопку «📬 Связаться с разработчиком» и прикрепляете диагностику:
- Прикрепляется только counts/metadata (количество текстов, использование квоты, версия браузера, выбранный VFS, последние ~10 событий init/import). Содержимого ваших текстов или заметок там нет.
- Превью того что отправится видно в форме перед отправкой.
- Отправка происходит только по вашему явному действию — клик на WhatsApp / Email / Copy. Автоматических beacon'ов нет.
#Хранение TTS-аудио на сервере
При воспроизведении предложения генерируется аудио (если не в кэше) и
кэшируется на сервере под hash'ом <text>+<voice>+<speed>+<pitch>. Это
не привязано к вашему userId или браузеру — кэш общий между всеми, кто
запросит ту же фразу с теми же настройками. Это эффективное использова-
ние квоты, но если вас беспокоит даже это — не запускайте TTS для
чувствительного контента.
#Кто разработчик и где код
- Single developer: Sindrom Radio.
- GitHub: SindromRadioSpb/tts-prototype-android
- Лицензия: MIT (исходный код).
- Контакты: см. кнопку «📬 Связаться с разработчиком» в приложении.
#Удаление ваших данных
В любой момент можно:
- Library → «⚠ Сбросить локальную библиотеку» — удалит всё локально.
- DevTools → Application → Storage → Clear site data → удалит OPFS.
- Аналогичные действия в браузере — «Clear browsing data».
Данные на сервере (TTS-кэш) хранятся по hash'у и не привязаны к вам лично — удаление невозможно индивидуально (это техническое ограничение shared cache). Если вы хотите чтобы конкретное аудио не лежало в кэше — напишите разработчику через feedback-модалку.
#Research mode (opt-in, Direction 11B)
С версии v3.2 в приложении появляется опциональный research-mode для ulpan-исследований (diploma project). Это единственное архитектурное исключение из offline-first инварианта — и оно строго opt-in.
Принципы (non-negotiable):
- Default OFF. Research-mode не активен у новых пользователей. Подключение требует явного согласия (informed consent screen).
- Анонимность. На сервер отправляется только anonymous
student_id(UUID, сгенерированный в браузере) + cohort code. Имя, email, IP, геолокация, user-agent — никогда не отправляются. - Только агрегаты. Server endpoint family
/api/research/v1/*принимает только daily-aggregate метрики (счётчики, длительности, гистограммы) — никогда raw text, тела заметок, аудио, или search query strings. - k-anonymity порог = 5. В когортах с менее чем 5 студентами per-student breakdown скрыт в teacher-dashboard'е (только общие агрегаты без детализации).
- One-click withdrawal. Любой студент может в один клик удалить
свои данные с сервера через
DELETE /api/research/v1/student/:uuid(UUID — это auth token, потому что он анонимен и хранится только на устройстве пользователя). После withdrawal: записи удаляются физически из cohort-логов, факт удаления записывается в audit log. - Прозрачность. В приложении доступен dashboard «What we collected from you» — список последних uploads с детальным содержимым каждого.
Что отправляется в research-mode (полный список):
См. docs/RESEARCH_METRICS_SCHEMA.md — это формальная спецификация wire
contract'а, server-side enforced строгой валидацией с recursive
forbidden-field check.
Кратко (per-day агрегаты):
- Время активности (heartbeat-based, в минутах).
- Количество сессий + распределение по часам суток (24 buckets).
- Общая длительность audio playback (мс).
- Счётчики: открытых текстов, прочитанных предложений, созданных заметок, reviewed карточек, search queries (только counts, без строк).
- Hebrew-specific: niqqud time ratio, replay-distribution histogram.
Что НЕ отправляется (server-side rejected at schema validation):
- Hebrew text content.
- Note body text.
- Search query strings.
- Audio bytes.
- Username / email / phone / name.
- IP / geolocation / user-agent.
- Device fingerprints.
Срок хранения: 2 года post-cohort-end (запись в
cohort_meta.retention_until), затем автоматическое удаление.
#Outcome data flow (Phase 11.6)
Помимо daily aggregates research-mode также собирает итоговые баллы экзамена для корреляционного анализа. Два равнозначных пути:
- Self-report от студента — кнопка «🎓 Сдать экзамен» в research-mode
панели. Студент сам вводит балл (0-100) + опционально confidence (1-5
Likert). Отправляется как обычный research-payload с
metrics.outcomepopulated, меткаoutcome_capture_method: "self-report". Anonymous, привязан только к UUID. - Teacher CSV upload — преподаватель через teacher dashboard загружает
CSV
student_id,pre_test_score,post_test_score,exam_date,uploaded_by. Bearer-auth по researcher token; bodies до 256 KB; merge semantics (incoming wins по student_id), atomic rewrite. Audit-log вdeletions.logфиксирует факт загрузки (counts only, без баллов).
Authority: Teacher CSV всегда перезаписывает self-report когда есть
конфликт по student_id. Это by-design (teacher — authoritative source);
documented в docs/RESEARCHER_GUIDE.md §4.
Linking: связь между UUID студента и его именем/email никогда не происходит автоматически — это требует отдельного opt-in действия студента (передать UUID преподавателю на бумаге при сдаче экзамена). Without that, исследователь видит только anonymous UUID + балл.
Withdrawal coverage: одна кнопка «🗑 Отозвать согласие» удаляет ВСЕ
данные с сервера — и daily payloads из <cohort>/<date>.jsonl, и outcome
строки из <cohort>/outcomes.csv. Audit-log фиксирует число удалённых
записей (без content).
#Изменения в этой политике
Будут отражены в CHANGELOG.md под соответствующей версией. Substantive
изменения (расширение того что собирается) сопровождаются явным
in-app banner'ом при первом открытии после обновления.
Last updated: 2026-05-13 (v3.2.0 — added Research mode + outcome data flow section)