live.tips — это копилка для чаевых с открытым кодом, сделанная для артистов. Проект ведёт Никита Рабыкин, разработчик-одиночка, а не компания. Если что-то из написанного ниже для вас важно, напишите на [email protected] — по этому адресу отвечает живой человек.
Эта политика честна даже в скучных местах. Мы лучше скажем «мы храним ваше имя столько же, сколько вы держите группу», чем заявим, что не храним ничего, и окажемся неправы.
Коротко
- Аккаунт необязателен. Приложение работает вообще без аккаунта, и это по-прежнему вариант по умолчанию. Если вы хотите, чтобы ваши группы и ваша история были на втором устройстве, вы можете войти — и тогда часть этого будет храниться на сервере, причём больше, чем раньше. Что именно и что нет — расписано ниже.
- Нет кук. Ни одной, нигде.
- Нет аналитики, нет слежки, нет рекламы, нет сторонних скриптов на этом сайте.
- Мы никогда не касаемся ваших денег. Чаевые идут напрямую от зрителя в собственный аккаунт артиста в Stripe, Revolut, MobilePay или Monzo. Баланса live.tips нет и не было никогда.
- Без аккаунта приложение обращается только к Stripe — ни к какому серверу live.tips. Если вы войдёте, это меняется: ваш ключ Stripe переезжает на наш сервер, и Stripe сообщает нам о ваших чаевых, чтобы мы могли выложить их на ваши другие устройства. Это честная цена входа, и она полностью расписана ниже.
- Push-уведомления — новое, необязательное и только для аккаунтов, в которые вошли. Ничего не отправляется на устройство, которое их не включало, а устройству без аккаунта не отправляется вовсе.
- Серверы, которые мы держим, — на Firebase от Google. Они существуют на случай, если артист включит Revolut, MobilePay или Monzo — или если он войдёт в аккаунт.
Этот сайт
Сайт статический и размещён на GitHub Pages. Как хостинг, GitHub получает IP-адрес и user-agent браузера каждого, кто открывает страницу, — это обычное логирование веб-сервера, оно происходит до того, как запустится хоть строчка нашего кода, и отключить его мы не можем. GitHub обрабатывает эти данные по собственному заявлению о конфиденциальности. Мы эти логи не читаем, и GitHub нам их не показывает.
Кроме этого, страницы, которые вы читаете, не подгружают ничего ни от кого: шрифты, иконки и картинки отдаёт сам live.tips. Нет ни Google Analytics, ни тег-менеджера, ни пикселя, ни встроенных виджетов.
Сайт хранит два значения в localStorage вашего браузера — оба задаёте вы сами, оба
доступны только этому сайту, и ни одно никуда не отправляется:
| Ключ | Что запоминает |
|---|---|
lt-landing-theme |
выбрали ли вы светлую, тёмную или автоматическую цветовую схему |
lt-langbar-dismissed |
что вы закрыли баннер «сайт также доступен на вашем языке» |
Очистка хранилища браузера удаляет их. Это не куки, ими ни с кем не делятся, и они никого не идентифицируют.
У приложения два режима, и вся история — в разнице между ними
Всё написанное ниже зависит от одного вопроса: вошли ли вы в аккаунт?
Режим первый — без аккаунта. По-прежнему по умолчанию, по-прежнему без изменений.
Приложение работает на устройстве самого артиста, и всё, что оно знает, живёт там же:
- Ограниченный ключ Stripe хранится в связке ключей устройства (Keychain на
iOS/macOS, Keystore на Android) и передаётся только на
api.stripe.com. - История чаевых, история сессий, цель, список песен для запросов и настройки приложения хранятся в локальном хранилище устройства. Сюда же входят имена и сообщения, которые зрители прикладывают к своим чаевым.
- Удаление приложения стирает всё это. Резервной копии в облаке на нашей стороне нет, потому что в этом режиме на нашей стороне нет облака.
Мы никогда ничего из этого не получаем. В приложении нет ни SDK аналитики, ни сборщика отчётов о сбоях, ни рекламного кода — их нет вовсе, а не «выключены». (Push-уведомления существуют, но это функция для вошедших в аккаунт, и они выключены, пока вы их не включите, — см. Режим второй. Устройству без аккаунта их не отправляют никогда.)
Два уточнения, чтобы утверждение «ни с кем не общается» оставалось буквально верным:
- Приложение раз в день запрашивает курсы валют у публичных API курсов
(
frankfurter.dev,open.er-api.com,currency-api.pages.dev). Это обычные запросы за публичным списком курсов. Они не несут никакой информации о вас, об артисте или о чаевых — но, как и любой веб-запрос, раскрывают этим сервисам ваш IP-адрес. - Если вы пользуетесь браузерной версией приложения, ваш браузер скачивает её с нашего статического хостинга (см. раздел Этот сайт выше).
Режим второй — вы вошли в аккаунт. Тогда часть данных намеренно покидает устройство.
Вход в аккаунт — осознанное действие. Никто не входит за вас, и ничто в приложении не перестаёт работать, если вы не войдёте никогда. Вы входите потому, что хотите второе устройство: телефон в кармане и планшет на сцене, показывающие один и тот же вечер, те же группы, ту же историю.
Это возможно, только если их держит сервер. Значит, он их держит, и это честная цена второго устройства.
Сервер — это Firebase, то есть Google. Завести аккаунт можно тремя способами:
- Вход через Apple или вход через Google — Firebase Auth получает то, что передаёт провайдер: идентификатор пользователя (uid) и, как правило, адрес электронной почты и имя. (У Apple можно скрыть почту; тогда Apple выдаёт нам вместо неё адрес-ретранслятор, а имя передаёт только в самый первый раз, когда вы входите.)
- Гостевой аккаунт — анонимный аккаунт без почты и без имени. Он синхронизируется и его можно отозвать, но восстановить его нечем, если вы потеряете устройство. Это uid и больше ничего. Гостевой аккаунт не может пользоваться ни серверным хранением ключа Stripe, ни push-уведомлениями, описанными ниже, потому что и то и другое требует аккаунта, который мы можем вернуть вам.
После входа аккаунт получает собственный закрытый уголок в базе данных Google Cloud
Firestore, по адресу users/<your uid>/. Правила безопасности отдают этот уголок этому
uid и никому больше — никакой другой аккаунт не может его прочитать, в том числе
подбором URL. Внутри:
| Что | Зачем это там |
|---|---|
| Ваши группы — названия, настройки копилки и способов оплаты, текст постера, цели и ваш список песен для запросов | чтобы группа существовала на каждом устройстве, где вы вошли |
| Настройки приложения, включая ваши предпочтения по уведомлениям | чтобы добавленное устройство сразу было настроено |
| Записи сессий и история чаевых — включая имена и сообщения, которые зрители прикладывают к чаевым, и любую песню, которую запросил зритель | потому что именно эту историю вы и попросили показать на другом устройстве |
| Живая сессия, идущая прямо сейчас | чтобы второй экран мог подключиться к сегодняшнему сету |
| Ваши устройства — имя, которое каждое даёт себе само («iPhone Никиты»), платформа и модель, язык интерфейса, когда его увидели впервые и в последний раз, и (если вы включили уведомления) push-токен | чтобы «Настройки → Безопасность» могли их перечислить, чтобы уведомление доходило до нужного устройства на нужном языке и чтобы вы могли любое отозвать |
| Небольшой документ профиля — выбранное вами имя аккаунта и то, каким провайдером вы вошли | чтобы переключатель аккаунтов мог его подписать |
| Лента уведомлений — ограниченный список недавних чаевых и запросов песен, пришедших, пока не шёл сет | чтобы вы могли наверстать то, что пропустили |
А теперь главное, прямым текстом: без аккаунта имя и сообщение зрителя никогда не покидают устройство артиста. С аккаунтом они хранятся на серверах Google под uid артиста как часть его собственной синхронизированной истории, и — как объясняют следующие два раздела — теперь именно наш сервер записывает их туда. Никакой другой аккаунт не может их прочитать, мы в них не заглядываем и ничего из них не выводим — но они там есть, и остаются там столько же, сколько существует группа, и вам стоит знать об этом до того, как вы войдёте.
Выход из аккаунта возвращает устройство в локальный режим. Данные аккаунта он не удаляет — см. Как всё удалить ниже.
Ваш ключ Stripe при входе переезжает на наш сервер
Это самое большое изменение и то, которое важнее всего прочитать.
Без аккаунта ваш ограниченный ключ Stripe никогда не покидает ваше устройство. Это Режим первый, и он не изменился.
Когда вы входите, он всё-таки уходит — к нам. Ключ шифруется (отдельным для каждого секрета ключом AES-256, который сам обёрнут Google Cloud KMS) и хранится на сервере в месте, где его не может прочитать обратно никто — ни другой аккаунт, ни даже вы сами. Он расшифровывается только внутри наших Cloud Functions, используется, чтобы общаться со Stripe от вашего имени, и больше никогда не выдаётся ни одному устройству.
Поскольку ключ теперь живёт у нас, Stripe сообщает о ваших чаевых прямо нашему серверу: мы регистрируем вебхук в вашем собственном аккаунте Stripe, и Stripe сообщает этому вебхуку каждый раз, когда чаевые оплачены. Наша функция записывает чаевые в историю вашего аккаунта (см. ниже). Приложение больше не опрашивает Stripe для аккаунта, в который вошли; оно обращается к Stripe только через узкий, фиксированный список операций на нашем сервере (создание вашей ссылки на чаевые, выпуск ссылки для запроса песни и чтение ваших собственных чаевых для сверки).
Итак, без эвфемизмов: для аккаунта, в который вошли, между Stripe и вашей историей теперь
есть сервер live.tips. Денег мы по-прежнему не касаемся — чаевые картой создаются в вашем
аккаунте Stripe, оседают на вашем балансе Stripe и выплачиваются по вашему графику Stripe,
ровно как раньше. Изменился путь данных, а не путь денег. Если вы никогда не входите,
ничего из этого к вам не относится, и приложение по-прежнему обращается напрямую к
api.stripe.com и больше ни к кому.
Добавление устройства по QR-коду
Чтобы добавить устройство, вы показываете QR-код с устройства, на котором уже вошли. Код случайный, одноразовый и живёт две минуты, и новое устройство не получает ничего, пока вы не нажмёте подтвердить на старом. Пока это рукопожатие открыто, мы храним код, имя, которое новое устройство дало себе само, и его платформу — и запись удаляется, когда код истекает. Сфотографированный QR-код бесполезен без вашего подтверждающего нажатия.
Запросы песен
Группа может включить запросы песен: тогда зрители выбирают песню из списка артиста и по желанию платят, чтобы поднять её выше в очереди. Запрос — это те же чаевые, которые вдобавок несут информацию о том, какую песню попросили, — так что те же имя и сообщение, которые зритель может приложить к чаевым, действуют и здесь, и они хранятся и удерживаются ровно так же, как любые другие чаевые (ниже). Публичная очередь, которую видит зритель, показывает только суммы по каждой песне — сколько песня собрала и на каком месте стоит — и не несёт имён зрителей. Без аккаунта весь список песен для запросов и его история живут только на устройстве.
Push-уведомления
Когда вы вошли в аккаунт, приложение может присылать вам push-уведомление — но только если вы его включите, по каждому устройству отдельно, и только после того, как операционная система устройства даст разрешение. Существует оно ради одного: чаевые или запрос песни, которые приходят, пока вы не ведёте сет, чтобы вы узнали о чаевых, которые иначе пропустили бы. Чаевые, пришедшие, пока ваша сцена в эфире, не присылают ничего — вы и так за ними смотрите.
- Чтобы доставить push, Firebase Cloud Messaging (FCM) от Google нужен push-токен устройства. Мы храним этот токен и язык интерфейса устройства в записи самого устройства под вашим аккаунтом, и он удаляется в тот момент, когда вы выключаете уведомления, отзываете устройство или выходите из аккаунта. Мёртвые токены подчищаются автоматически.
- Само уведомление говорит, что пришло, — сумму, а также имя зрителя или название песни, если он их оставил. Тот же короткий список хранится в ленте уведомлений вашего аккаунта, ограниченной последней сотней записей, чтобы вы могли пролистать то, что пришло, пока вас не было.
- В вебе для доставки push нужен небольшой service worker в корне сайта и SDK обмена
сообщениями Firebase, который ваш браузер в первый раз скачивает у Google
(
gstatic.com). Дальше web push несёт собственная push-служба вашего браузера (для Chrome — это служба Google). Ничего из этого не загружается, пока вы не включили уведомления. - Гостевой аккаунт и устройство без аккаунта не получают push, потому что для push нужен аккаунт, которому мы можем доставить, и токен, который вы решили дать.
Где всё это физически находится
Firebase Auth, Cloud Firestore, наши Cloud Functions и ключ Cloud KMS, который обёртывает
ваш секрет Stripe, работают в Европейском союзе: база данных — в мультирегионе Google
eur3, функции и связка ключей — в europe-west1. Google выступает нашим обработчиком по
условиям конфиденциальности и безопасности Firebase
и собственной политике конфиденциальности. Как и
любой крупный провайдер, Google может привлекать инфраструктуру за пределами ЕС для
поддержки и безопасности; это регулируется теми условиями, а не нами. Push-уведомления,
будучи переданы в Firebase Cloud Messaging и push-службе вашего браузера или телефона, идут
по инфраструктуре этих компаний, чтобы дойти до вашего устройства.
Stripe
Когда зритель платит картой, он находится на странице оплаты Stripe, а не на нашей. Stripe собирает и обрабатывает его платёжные данные как самостоятельный контролёр по политике конфиденциальности Stripe. Мы никогда не видим номеров карт.
Как ваши чаевые доходят до вас, зависит от режима:
- Без аккаунта приложение артиста читает его собственные чаевые из Stripe с помощью его
собственного ограниченного ключа — напрямую с устройства на
api.stripe.com. Никакого сервера live.tips на этом пути нет. - Когда вы вошли, ключ живёт на нашем сервере (зашифрованный, как выше), и Stripe сообщает о каждых чаевых нашему вебхуку, который записывает их в собственную историю этого артиста в Firestore. В этом режиме на пути есть сервер live.tips — для данных о чаевых, но никогда для денег. Имя и сообщение зрителя, если он их оставил, идут вместе с чаевыми в собственную историю этого артиста и на этом останавливаются.
Ретранслятор — только если включены Revolut, MobilePay или Monzo
Тех, у кого настроен только Stripe, это не касается вовсе.
Revolut, MobilePay и Monzo не дают приложению никакой возможности подтвердить, что платёж
состоялся, поэтому такие чаевые проходят через небольшой open-source-ретранслятор, который
мы держим на Firebase: Cloud Functions и Firestore в europe-west1, а страница чаевых
для зрителя отдаётся с tip.live.tips/t/<id>. Денег он не касается никогда. Вот всё,
что он обрабатывает.
Что хранит артист
При создании страницы чаевых сохраняются отображаемое имя артиста, его публичное сообщение, его валюта и те платёжные реквизиты, которые он решил опубликовать (ссылка на оплату в Stripe, имя пользователя в Revolut, Box ID в MobilePay, имя пользователя в Monzo), а если включены запросы песен — его публичный список песен и цены за каждую. Всё это — сведения, которые артист и так намеренно публикует для зрителей.
- Срок хранения: страница чаевых, за которой нет аккаунта, удаляется автоматически после 90 дней без активности. Страница чаевых, принадлежащая аккаунту, живёт столько же, сколько группа, к которой она относится.
- Артист может удалить её немедленно из приложения, в любой момент.
- Ни адрес электронной почты, ни пароль, ни настоящее имя, ни банковские реквизиты здесь не собираются.
- Секрет страницы хранится только в виде хеша. Мы не смогли бы назвать вам этот секрет, даже если бы вы попросили; мы можем только проверить предъявленный.
Что отправляет зритель
Форма чаевых спрашивает сумму и по желанию имя и сообщение — а для запроса песни ещё и какую песню. Это вся форма. Ни почты, ни телефона, ни аккаунта.
Куда уходит написанный зрителем текст и как надолго, зависит от того, вошёл ли артист в аккаунт:
- Если за страницей чаевых нет аккаунта, чаевые записываются в очередь доставки — это один документ, который существует затем, чтобы быть переданным на экран артиста. Когда экран показывает чаевые, устройство артиста удаляет этот документ. Удаление и есть подтверждение доставки. Если экран артиста не в сети — телефон заблокирован, нет связи — чаевые ждут в этой очереди до одного часа, чтобы они просто не пропали, и передаются в тот момент, когда экран снова подключится. Если никто не подключится, они удаляются непрочитанными — их подчищает регулярная задача. Для артиста без аккаунта эта очередь — единственное место, где написанный зрителем текст вообще хранится на нашем сервере, и один час — его жёсткий предел.
- Если страница чаевых принадлежит аккаунту, в который вошли, никакой очереди нет. Наш сервер записывает чаевые прямо в собственную историю этого артиста под его uid — в сегодняшнюю сессию, если идёт сет, или в собственный архив группы, если нет. Там они остаются столько же, сколько существует группа; это собственная история артиста, и ровно ради неё он и входил. Это та же история, в которую пишет вебхук Stripe выше.
- Ваши имя и сообщение также подставляются в примечание к платежу, которое открывается в Revolut, MobilePay или Monzo, — именно так артист узнаёт, кто оставил чаевые. Дальше эти компании обрабатывают их по собственным политикам конфиденциальности.
- Ретранслятор не ведёт межартистовой истории чаевых. Он не может показать ни вам, ни нам, ни кому-либо ещё список того, кто кому сколько оставил между разными артистами.
IP-адреса и защита от злоупотреблений
Открытой форме, куда может отправить что угодно кто угодно, нужна какая-то защита от ботов, поэтому:
- Ваш IP-адрес передаётся в Cloudflare Turnstile — проверку на ботов, которая работает на странице чаевых, — чтобы убедиться, что вы не бот. Turnstile — продукт Cloudflare, и он используется вместо CAPTCHA, которая вас профилирует. Turnstile и наш DNS — это всё, что Cloudflare для нас ещё делает; сам ретранслятор теперь работает на Firebase. См. политику конфиденциальности Cloudflare.
- Ваш IP-адрес также используется для ограничения частоты запросов — отправки чаевых, создания страницы чаевых, погашения кода добавления устройства. Для этого мы храним криптографический хеш IP-адреса с солью, а не сам IP-адрес, примерно два часа, а затем удаляем его. Соль — это серверный секрет: без неё код отказывается хранить хоть что-нибудь, вместо того чтобы держать хеш, который можно обратить.
- Операционные логи Google несколько дней фиксируют технические детали запросов к ретранслятору — URL, время, статус. Наш код намеренно не пишет в логи ни имён, ни сообщений, ни секретов, ни заголовков. Google выступает нашим обработчиком.
Счётчики
Ретранслятор считает, сколько чаевых он передал для конкретной страницы чаевых, чтобы мы могли замечать злоупотребления и понимать, пользуются ли этим вообще. Это число. Данных зрителей в нём нет.
Кто что обрабатывает
| Кто | Что получает | Зачем |
|---|---|---|
| Google (Firebase) | Аккаунты, синхронизированные данные вошедшего артиста, зашифрованный ключ Stripe, ретранслятор, push-токены и доставку, логи сервера | Необязательный аккаунт, необязательный ретранслятор и push-уведомления |
| Google Cloud KMS | Ключ, который обёртывает секрет Stripe вошедшего артиста (никогда — сам секрет в открытом виде) | Чтобы хранимый ключ Stripe оставался нечитаемым в покое |
| Stripe | Платёжные данные зрителя, как самостоятельный контролёр; а для вошедшего артиста — события о чаевых, отправляемые нашему вебхуку | Чаевые картой |
| Cloudflare | IP-адрес зрителя — для проверки Turnstile на странице чаевых. И наш DNS. | Чтобы боты не лезли в форму чаевых |
| GitHub | IP-адрес и user-agent каждого, кто открывает этот сайт | Хостинг сайта |
| Push-служба вашего браузера / телефона (например, Google для Chrome) | Push-токен и содержимое уведомления, если вы включили уведомления | Доставка push-уведомлений |
| Revolut / MobilePay / Monzo | Всё, что зритель делает в их собственном приложении, включая примечание к платежу | Эти способы оплаты |
Мы никому ничего не продаём, и никого другого в этом списке нет.
Правовое основание, если оно вам нужно (GDPR)
- Работа аккаунта, о котором вы попросили, синхронизация ваших собственных данных на ваши собственные устройства, хранение вашего ключа Stripe, чтобы ваши чаевые доходили до вашей истории, работа ретранслятора для артиста, который его включил, доставка чаевых зрителя на тот экран, куда они были адресованы, и отправка push-уведомления, которое вы включили: исполнение услуги, о которой вы попросили.
- Ограничение частоты запросов, Turnstile, квоты по хешам IP и отзыв устройств: законный интерес в том, чтобы бесплатный открытый сервис не был уничтожен ботами и мошенничеством, и в том, чтобы аккаунты артистов оставались защищёнными.
- Логи сервера: законный интерес в эксплуатации и защите сервиса.
Как всё удалить
Это важнее любого обещания, которое мы могли бы дать, поэтому вот что есть на сегодня — включая то, чего нет.
- Без аккаунта: удалите приложение. Это всё, и всего этого больше нет.
- Группа: удаление группы в приложении стирает облачные данные этой группы — её настройки, её ключи, её сессии, её историю чаевых — вместе с копией на устройстве.
- Страница чаевых: удалите или пересоздайте её в приложении, и она мгновенно стирается с ретранслятора вместе со всеми ожидающими чаевыми.
- Push-уведомления: выключите их на устройстве — и его push-токен удаляется. Лента уведомлений очищается вместе с группой или аккаунтом.
- Устройство: «Настройки → Безопасность» перечисляют ваши устройства. Вы можете отозвать одно из них или выйти везде, кроме текущего, — это завершает сессию каждого другого устройства немедленно, а не когда-нибудь потом.
- Весь аккаунт, в одно нажатие: такой кнопки в приложении пока нет. Мы лучше признаем это, чем сделаем вид, что всё иначе. Пока её нет, напишите на [email protected], и мы удалим аккаунт и всё, что под ним, вручную. А пока вы уже сейчас можете удалить каждую группу — это уносит всё содержательное, включая хранимый ключ Stripe, и оставляет позади пустой аккаунт.
Ваши права
Вы можете попросить нас предоставить копию, исправить или удалить всё, что у нас есть о вас, а также подать жалобу в национальный орган по защите данных. Пишите на [email protected].
На практике почти всё и так в ваших руках: артист может мгновенно удалить страницу чаевых или группу из приложения, недоставленные чаевые зрителей на странице без аккаунта испаряются в течение часа, а если вы никогда не входили в аккаунт, ничего из этого нигде и не было, кроме вашего собственного устройства.
Дети
live.tips не предназначен для детей, и мы сознательно не обрабатываем их данные.
Изменения
Мы будем обновлять эту страницу по мере изменения программы. Поскольку весь проект имеет открытый код, каждая прошлая версия этой политики есть в публичной истории git — вы можете посмотреть точный дифф: что и когда изменилось.
Язык
Эта политика публикуется на всех языках, которые поддерживает сайт, — для удобства. Если перевод и английская версия расходятся, имеет силу английская версия.