[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"technologies":3,"\u002Fportfolio\u002Fcashback-loyalty-platform":167,"glossary":524},[4,10,15,21,26,32,38,43,48,53,58,63,68,73,77,82,87,92,97,103,108,113,118,123,128,133,138,143,147,152,157,162],{"title":5,"description":6,"slug":7,"category":8,"icon":9},"Android","Каждое наше приложение выходит и на Android — платформенные API, фоновое выполнение, разрешения и требования магазина вместе с ними.","android","framework","logos:android-icon",{"title":11,"description":12,"slug":13,"category":8,"icon":14},"Angular","Фронтенд-фреймворк, в котором мы работаем, когда продукт уже на Angular, — строгая структура, подходящая большим долгоживущим приложениям.","angular","logos:angular-icon",{"title":16,"description":17,"slug":18,"category":19,"icon":20},"Dart","Язык, на котором написано каждое наше Flutter-приложение, — строгая null safety, полноценный pattern matching и компиляция в нативный код и веб.","dart","language","logos:dart",{"title":22,"description":23,"slug":24,"category":8,"icon":25},"Django","Python-фреймворк, который мы берём, когда продукту нужны админка, аутентификация и модель данных в первый же день, а не самописный сервис.","django","logos:django-icon",{"title":27,"description":28,"slug":29,"category":30,"icon":31},"Docker","Каждый наш сервис поставляется в виде контейнера, поэтому на ноутбуке, в CI и в продакшене работает один и тот же артефакт, а не три разных.","docker","infrastructure","logos:docker-icon",{"title":33,"description":34,"slug":35,"category":36,"icon":37},"Fastlane","Автоматизация релизов в нашей мобильной разработке — подпись, сборки и загрузка в сторы идут из CI, а не с ноутбука одного инженера в день релиза.","fastlane","tools","logos:fastlane",{"title":39,"description":40,"slug":41,"category":8,"icon":42},"Flutter","Наш основной мобильный стек с 2018 года — одна кодовая база на Dart для iOS, Android, веба и десктопа без отдельной команды под каждую платформу.","flutter","logos:flutter",{"title":44,"description":45,"slug":46,"category":36,"icon":47},"Git","Все проекты, к которым мы прикасаемся, живут в Git — ревью пул-реквестов, CI на каждой ветке и история, понятная и спустя месяцы.","git","logos:git-icon",{"title":49,"description":50,"slug":51,"category":19,"icon":52},"Go","Наш бэкенд-язык для real-time API и сервисов под нагрузкой — маленькие бинарники, быстрая сборка и конкурентность, которая остаётся читаемой.","go","logos:gopher",{"title":54,"description":55,"slug":56,"category":30,"icon":57},"Google Cloud","Облако, в котором работают наши продакшен-нагрузки, — управляемый Kubernetes, хранилище и сеть без серверов, которые надо обслуживать руками.","gcp","logos:google-cloud",{"title":59,"description":60,"slug":61,"category":36,"icon":62},"Gradle","Система сборки, через которую проходит каждый Android-релиз, — флейворы, конфигурации подписи и вся обвязка зависимостей под Flutter-приложением.","gradle","logos:gradle",{"title":64,"description":65,"slug":66,"category":30,"icon":67},"Helm","Так мы упаковываем деплой в Kubernetes — сервис, конфигурация, секреты и ingress как одна версионируемая единица, которую можно выкатить и откатить.","helm","logos:helm",{"title":69,"description":70,"slug":71,"category":19,"icon":72},"Kotlin","То, что мы берём, когда Flutter-приложению нужен настоящий Android под ним, — platform channels, фоновые задачи и интеграции с нативными SDK.","kotlin","logos:kotlin-icon",{"title":74,"description":75,"slug":76,"category":8,"icon":72},"Kotlin Multiplatform","Общая бизнес-логика для iOS и Android, а нативный интерфейс у каждой платформы свой, — альтернатива, когда Flutter не подходит.","kmp",{"title":78,"description":79,"slug":80,"category":30,"icon":81},"Kubernetes","Так мы запускаем сервисы в продакшене — деплой в Helm-чартах, откатываемые выкатки и масштабирование, для которого не нужен человек в три ночи.","kubernetes","logos:kubernetes",{"title":83,"description":84,"slug":85,"category":30,"icon":86},"NATS","Лёгкий обмен сообщениями между сервисами — publish\u002Fsubscribe и request\u002Freply без эксплуатационного веса полноценного кластера брокера.","nats","logos:nats-icon",{"title":88,"description":89,"slug":90,"category":8,"icon":91},"Nuxt","Vue с серверным рендерингом, роутингом и SEO из коробки — так мы делаем сайты и веб-приложения, которые должны быстро грузиться и индексироваться.","nuxt","logos:nuxt-icon",{"title":93,"description":94,"slug":95,"category":19,"icon":96},"PHP","Там, где PHP-бэкенд уже есть: дорабатываем его, интегрируемся с ним и делаем мобильные и веб-клиенты, которые он обслуживает.","php","logos:php",{"title":98,"description":99,"slug":100,"category":101,"icon":102},"PostgreSQL","Наша база данных по умолчанию — от проектирования схемы до настройки индексов мы берём её, если у продукта нет конкретной причины взять другую.","postgres","database","logos:postgresql",{"title":104,"description":105,"slug":106,"category":19,"icon":107},"Python","Наш язык для бэкендов, работы с данными и AI-интеграций — включая Python-биндинги, которые мы выпускаем к собственным инструментам на Rust.","python","logos:python",{"title":109,"description":110,"slug":111,"category":8,"icon":112},"React","Фронтенд-библиотека, в которой мы работаем, когда продукт уже на React, — компоненты, хуки и выросшая вокруг них экосистема.","react","logos:react",{"title":114,"description":115,"slug":116,"category":101,"icon":117},"Redis","Место для данных, которые должны быть быстрыми и которые не жалко пересчитать, — кэши, сессии, лимиты и очереди фоновых задач.","redis","logos:redis",{"title":119,"description":120,"slug":121,"category":19,"icon":122},"Ruby","Язык, на котором написана автоматизация наших мобильных релизов, — лейны Fastlane, кастомные действия и связка с CI, доставляющая сборки в сторы.","ruby","logos:ruby",{"title":124,"description":125,"slug":126,"category":19,"icon":127},"Rust","Куда мы идём, когда важны и скорость, и корректность, — рендеринг документов, CLI-инструменты и сервисы, которые обязаны оставаться быстрыми и предсказуемыми.","rust","simple-icons:rust",{"title":129,"description":130,"slug":131,"category":101,"icon":132},"SQLite","База данных, которая поставляется внутри приложения, — локальные кэши, offline-first хранилище и всё, что должно работать без сети.","sqlite","logos:sqlite",{"title":134,"description":135,"slug":136,"category":8,"icon":137},"Strapi","Headless CMS, к которой мы обращаемся, когда контент должны вести сами редакторы, — готовая админка и чистый API вместо самописных.","strapi","logos:strapi-icon",{"title":139,"description":140,"slug":141,"category":19,"icon":142},"Swift","То, что мы берём, когда Flutter-приложению нужен настоящий iOS под ним, — platform channels, интеграции нативных SDK, виджеты и App Clips.","swift","logos:swift",{"title":144,"description":145,"slug":146,"category":8,"icon":142},"SwiftUI","UI-фреймворк Apple, на котором мы делаем нативные поверхности, недоступные Flutter-приложению, — виджеты, App Clips и расширения.","swiftui",{"title":148,"description":149,"slug":150,"category":8,"icon":151},"Tailwind CSS","Так мы стилизуем весь фронтенд — утилитарные классы и дизайн-токены вместо таблицы стилей, которая только растёт и никогда не чистится.","tailwind","logos:tailwindcss-icon",{"title":153,"description":154,"slug":155,"category":19,"icon":156},"TypeScript","Стандарт для всего, что мы пишем для браузера и для Node-сервисов, — типы ловят ошибки интеграции раньше, чем код доходит до ревью.","typescript","logos:typescript-icon",{"title":158,"description":159,"slug":160,"category":8,"icon":161},"Vue","Наш фронтенд-фреймворк для админок, дашбордов мерчантов и веб-приложений, которые должны оставаться поддерживаемыми годами, а не спринтами.","vue","logos:vue",{"title":163,"description":164,"slug":165,"category":36,"icon":166},"Whisper","Открытая модель распознавания речи от OpenAI — движок транскрипции для голосового ввода, который работает и как бэкенд-сервис, и прямо на устройстве в приложении.","whisper","simple-icons:openai",{"id":168,"title":169,"body":170,"categories":500,"client":504,"date":505,"description":506,"duration":507,"extension":508,"image":509,"links":512,"meta":513,"metaDescription":514,"navigation":515,"ogDescription":516,"path":517,"seo":518,"slug":519,"stem":520,"technologies":521,"updated":522,"__hash__":523},"projects_ru\u002Fportfolio\u002Fcashback-loyalty-platform.md","Платформа кэшбэка и лояльности",{"type":171,"value":172,"toc":485},"minimark",[173,178,182,195,203,206,212,216,220,227,230,241,244,248,256,267,271,274,278,285,307,310,314,317,320,326,336,342,346,368,371,374,378,385,389,405,416,424,428,431,434,460,477,481],[174,175,177],"h2",{"id":176},"обзор-проекта","Обзор проекта",[179,180,181],"p",{},"Наш клиент управляет платформой кэшбэка, которая позволяет офлайн-магазинам — кафе, салонам, бутикам, локальной рознице — вознаграждать своих клиентов и, что не менее важно, наконец-то узнать их поближе. У офлайн-бизнеса редко есть те данные о клиентах, которые онлайн-магазины принимают как должное: кто их постоянные посетители, когда они заходили в последний раз, что заставляет их возвращаться. Платформа закрывает этот пробел, вкладывая программу кэшбэка и лояльности в руки каждого участвующего магазина, а брендированное приложение — в карман каждого клиента.",[179,183,184,185,189,190,194],{},"Бизнес-модель требует не одного приложения, а целого ",[186,187,188],"em",{},"семейства",": флагманского потребительского приложения, где покупатели находят участвующие магазины и отслеживают кэшбэк, отдельного приложения для мерчантов, чтобы магазины подключались и вели собственные программы вознаграждений, и растущего каталога ",[191,192,193],"term",{"slug":193},"white-label"," приложений — каждое из них полностью брендированное, самостоятельно публикуемое приложение кэшбэка для партнёрского бренда или розничной сети, и все они работают на одном продукте.",[179,196,197,198,202],{},"Со временем экосистема выросла до ",[199,200,201],"strong",{},"15+ работающих мобильных приложений",". Инженерная задача состояла не в том, чтобы хорошо сделать одно приложение, — а в том, чтобы создать единую кодовую базу, которая может стать любым числом брендированных приложений кэшбэка без линейного роста затрат на поддержку с каждым новым партнёром.",[179,204,205],{},"Мы отвечали за всю систему целиком: общий потребительский клиент, приложение для мерчантов, парк white-label приложений, движок правил кэшбэка и бэкенд-сервисы, а также внутренние админ-инструменты, которые превратили «запуск нового брендированного приложения» из многодневной инженерной задачи в форму самообслуживания.",[207,208,209],"nda-notice",{},[179,210,211],{},"Проект закрыт соглашением о неразглашении. Клиент, партнёрские бренды, стоящие за white-label приложениями, и опубликованные листинги в сторах не называются — на скриншотах ниже продукт показан на тестовых данных.",[213,214],"gallery",{":images":215},"[{\"url\": \"\u002Fprojects\u002Fcashback-loyalty-platform\u002Fimages\u002F01.webp\", \"alt\": \"Главный экран приложения с балансом кэшбэка и бонусом за приглашение\"}, {\"url\": \"\u002Fprojects\u002Fcashback-loyalty-platform\u002Fimages\u002F02.webp\", \"alt\": \"Страница магазина со ставкой кэшбэка за покупку\"}, {\"url\": \"\u002Fprojects\u002Fcashback-loyalty-platform\u002Fimages\u002F03.webp\", \"alt\": \"Лента ваучеров и новостей магазинов\"}, {\"url\": \"\u002Fprojects\u002Fcashback-loyalty-platform\u002Fimages\u002F05.webp\", \"alt\": \"Настройка отдельного white-label приложения\"}, {\"url\": \"\u002Fprojects\u002Fcashback-loyalty-platform\u002Fimages\u002F06.webp\", \"alt\": \"Список white-label приложений в админке\"}]",[174,217,219],{"id":218},"одна-кодовая-база-много-приложений","Одна кодовая база, много приложений",[179,221,222,223,226],{},"Флагманское потребительское приложение и каждый white-label вариант работают на ",[199,224,225],{},"единой кодовой базе",". Нет форков, нет веток под отдельные бренды и нет скопированных проектов, которые нужно синхронизировать. То, что различается между приложениями — брендинг, тема, фирменный стиль, фиче-флаги, конфигурация вознаграждений и метаданные для сторов, — выражено целиком через конфигурацию, которая живёт вне кода.",[179,228,229],{},"Мы построили клиент вокруг системы flavor-ов и конфигураций: единый бинарный «чертёж», который определяет фирменный стиль на этапе сборки из конфигурационного бандла конкретного приложения. Цвета, типографика, логотипы, сплэш-экраны, иконки приложений, идентификаторы бандлов и наборы включённых функций инжектируются для каждого flavor-а. Ошибка, исправленная один раз, или функция, выпущенная один раз, попадает во все приложения парка в следующем релизе — нет расхождений между брендами, которые нужно поддерживать.",[179,231,232,233,236,237,240],{},"Важно, что рычагами, определяющими каждый бренд, управляют ",[199,234,235],{},"менеджеры без навыков программирования",". Через админ-интерфейс нетехнический сотрудник задаёт для нового приложения ",[199,238,239],{},"иконки, цвета, яркость (светлую или тёмную тему) и часть подписей"," — и эти настройки попадают прямо в сборку без участия разработчика. Те, кто отвечает за внешний вид бренда, могут менять его напрямую, а не заводить тикет и ждать инженеров.",[179,242,243],{},"Это и есть ключевой экономический рычаг проекта: предельная стоимость шестнадцатого приложения близка к нулю, потому что это тот же код, что и у первого, только с другой конфигурацией.",[174,245,247],{"id":246},"нативная-конфигурация-сборки-на-dart","Нативная конфигурация сборки на Dart",[179,249,250,251,255],{},"Жизнеспособность парка white-label приложений зависит от нативной конфигурации сборки — настроек Android и iOS, которые действительно важны для сторов. Идентификаторы приложений и бандлов, отображаемые названия приложений, номера версий и сборок, настройка подписи, ресурсы иконок и сплэш-экранов, а также записи по каждому flavor-у в ",[252,253,254],"code",{},"build.gradle"," и в проекте Xcode — всё это должно быть корректным для каждого отдельного приложения и каждой отдельной сборки.",[179,257,258,259,262,263,266],{},"Вместо того чтобы поддерживать это вручную, мы написали ",[199,260,261],{},"собственный инструментарий на Dart, который программно управляет конфигурацией сборки для Android и iOS",". Получив конфигурационный бандл бренда, инструмент перезаписывает соответствующие записи в Gradle, манифесте, ",[252,264,265],{},"Info.plist"," и каталоге ресурсов под нужный flavor перед запуском сборки. Хранение этой логики на Dart означает, что она использует тот же источник истины, что и Flutter-клиент, и выполняется как полноценный шаг нашего процесса сборки — поэтому нативная конфигурация бренда генерируется детерминированно из его конфигурации и никогда не правится вручную.",[174,268,270],{"id":269},"приложение-для-мерчантов","Приложение для мерчантов",[179,272,273],{},"Офлайн-магазинам нужен был собственный инструмент — не урезанная версия потребительского приложения, а специально созданное приложение для управления программой вознаграждений и понимания своих клиентов. Из приложения для мерчантов владелец магазина за считанные минуты подключается к платформе, задаёт свои правила кэшбэка и скидок, подтверждает покупки клиентов для начисления кэшбэка и наконец видит, кто его клиенты: сколько новых, сколько вернувшихся, как часто они заходят и как работает каждая акция. Для многих из этих бизнесов это первое структурированное представление о своей клиентской базе за всё время. Мы построили его на том же фундаменте Flutter и общей библиотеке компонентов, что и потребительские приложения, поэтому обновления дизайн-системы и платформенные исправления распространяются на обе аудитории, а специфичные для мерчантов сценарии живут в собственных модулях.",[174,275,277],{"id":276},"настраиваемые-правила-кэшбэка-и-скидок","Настраиваемые правила кэшбэка и скидок",[179,279,280,281,284],{},"Сердце платформы — гибкий ",[199,282,283],{},"движок правил",", который позволяет каждому магазину проектировать собственные вознаграждения без нашей помощи. Через приложение для мерчантов магазин составляет правила:",[286,287,288,295,301],"ul",{},[289,290,291,294],"li",{},[199,292,293],{},"Кэшбэк за покупку"," — процент или фиксированная сумма, возвращаемая на баланс клиента за каждую подходящую покупку.",[289,296,297,300],{},[199,298,299],{},"Бонус на день рождения"," — вознаграждение, автоматически начисляемое около дня рождения клиента, чтобы вернуть его в магазин.",[289,302,303,306],{},[199,304,305],{},"Бонус за приглашение"," — реферальное вознаграждение, которое выплачивается, когда действующий клиент приглашает друга, тот присоединяется и совершает первую покупку.",[179,308,309],{},"Правила — это данные, а не код: каждый магазин выбирает своё сочетание, задаёт суммы, лимиты и сроки действия, а движок применяет их в момент покупки. Поскольку правила живут в конфигурации, магазин может сам запустить акцию ко дню рождения или изменить ставку кэшбэка — мгновенно, во всём своём приложении, — и мы не выпускаем для этого ни одного релиза.",[174,311,313],{"id":312},"админ-интерфейс-и-автоматизированный-сборочный-конвейер","Админ-интерфейс и автоматизированный сборочный конвейер",[179,315,316],{},"Самая заметная часть системы — внутренний админ-интерфейс. Подключение нового white-label бренда раньше было инженерной задачей: создать конфигурацию, зарегистрировать идентификаторы бандлов, сгенерировать ресурсы для подписи, настроить листинги в сторах и добавить новый таргет в CI. Мы свели всё это в единое веб-приложение, которым менеджеры управляют без написания кода.",[179,318,319],{},"Менеджер заполняет форму — название бренда, тема, ресурсы, метаданные стора, набор функций — и система делает остальное:",[179,321,322,325],{},[199,323,324],{},"Генерация конфигурации",": Админ-интерфейс сохраняет конфигурацию и ресурсы нового бренда и формирует конфигурационный бандл для конкретного flavor-а, который использует Flutter-клиент.",[179,327,328,331,332,335],{},[199,329,330],{},"Регистрация в конвейере",": Таргет нового приложения автоматически регистрируется в ",[191,333],{"slug":334},"ci-cd"," конвейере. Сборочная система подхватывает новый flavor, запускает наш собственный инструментарий на Dart для применения нативной конфигурации Android и iOS и выпускает подписанные артефакты для обеих платформ.",[179,337,338,341],{},[199,339,340],{},"Запуски в режиме самообслуживания",": То, что раньше требовало участия разработчика для каждого нового бренда, стало повторяемым процессом на основе формы. Бизнес может масштабировать число опубликованных приложений, не масштабируя размер инженерной команды.",[174,343,345],{"id":344},"автоматизация-сборки-и-деплоя-на-fastlane","Автоматизация сборки и деплоя на Fastlane",[179,347,348,349,355,356,361,362,367],{},"Весь процесс сборки и релиза автоматизирован от начала до конца с помощью ",[350,351,33],"a",{"href":352,"rel":353},"https:\u002F\u002Ffastlane.tools",[354],"nofollow"," — open-source инструментария для автоматизации сборки и развёртывания мобильных приложений. Мы используем его, чтобы стандартизировать каждый шаг, который иначе был бы ручным и подверженным ошибкам в масштабе 15+ приложений: управление подписью и provisioning-профилями, сборку и подпись бинарников iOS и Android, а также публикацию каждого приложения в ",[350,357,360],{"href":358,"rel":359},"https:\u002F\u002Fdocs.fastlane.tools\u002Fgetting-started\u002Fios\u002Fappstore-deployment\u002F",[354],"App Store"," и ",[350,363,366],{"href":364,"rel":365},"https:\u002F\u002Fdocs.fastlane.tools\u002Fgetting-started\u002Fandroid\u002Frelease-deployment\u002F",[354],"Google Play"," вместе с метаданными и скриншотами.",[179,369,370],{},"Поскольку все приложения используют единую конфигурацию Fastlane, параметризованную по flavor-у, релиз всего парка — это единая повторяемая операция. Новый white-label бренд наследует ровно тот же проверенный путь деплоя, что и флагманское приложение, — без написания отдельных скриптов релиза.",[179,372,373],{},"Админ-интерфейс — это приложение на Nuxt, работающее поверх наших PHP-сервисов и хранилища данных PostgreSQL, с инструментами на Ruby и Fastlane, оркестрирующими автоматизацию сборки и релиза.",[174,375,377],{"id":376},"бэкенд-и-сервисы","Бэкенд и сервисы",[179,379,380,381,384],{},"В основе каждого приложения лежит общий бэкенд, который ведёт ",[199,382,383],{},"реестр кэшбэка (ledger)",", движок правил, профили клиентов и конфигурацию по брендам. Единый набор сервисов обеспечивает работу всего парка приложений, а контекст бренда определяется для каждого запроса — поэтому клиент в любом white-label приложении, во флагманском приложении или магазин в приложении для мерчантов обращается к одному и тому же проверенному API, ограниченному его брендом. Реестр фиксирует каждое начисление и списание, поэтому балансы всегда поддаются аудиту, а профили клиентов дают каждому магазину то понимание своей аудитории, которого офлайн-рознице обычно не хватает.",[174,386,388],{"id":387},"отложенный-deep-linking-и-бонус-за-приглашение","Отложенный deep linking и бонус за приглашение",[179,390,391,392,395,396,400,401,404],{},"Фича, ради которой всё это понадобилось, — ",[199,393,394],{},"бонус за приглашение",". Платформа растёт за счёт рефералов: довольный клиент приглашает друга, тот нажимает на ссылку-приглашение — но приложения у него, как правило, ещё нет. С обычным ",[191,397,399],{"slug":398},"deep-linking","deep link"," контекст приглашения терялся в момент, когда друг попадал в стор: он устанавливал приложение, открывал его, оказывался на обычном главном экране — и связь между пригласившим и приглашённым исчезала, а вместе с ней и бонус за приглашение, обещанный обеим сторонам. Самый вирусный момент в продукте был сломан на самом важном шаге. Мы починили его с помощью ",[199,402,403],{},"отложенного deep linking",", чтобы приглашение переживало установку.",[179,406,407,408,411,412,415],{},"Поскольку весь парк использует одну кодовую базу, фича была построена один раз, и каждое брендированное приложение — флагман, приложение мерчанта и все white-label варианты — унаследовало её автоматически. Мы реализовали её штатными механизмами самих платформ, а не сторонним сервисом: лёгкий ",[199,409,410],{},"iOS App Clip"," перехватывает ссылку-приглашение ещё до того, как существует полное приложение, и передаёт её через общий контейнер App Group, а ",[199,413,414],{},"Google Play Install Referrer API"," несёт полезную нагрузку на Android. Очередь отложенных ссылок удерживает приглашение до тех пор, пока приложение не будет готово, а новый клиент не зарегистрируется и не войдёт в аккаунт, — только тогда реферал атрибутируется и бонус за приглашение начисляется и пригласившему, и новому клиенту, поэтому вознаграждение срабатывает корректно, даже несмотря на то, что путь проходит через установку и первый вход при холодном старте.",[179,417,418,419,423],{},"Полный технический разбор подхода — включая то, почему перестало работать распространённое решение, — мы описали в статье ",[350,420,422],{"href":421},"\u002Fblog\u002Fdeferred-deep-linking-app-clips-install-referrer","Отложенный deep linking после Firebase Dynamic Links: App Clips + Play Install Referrer",".",[174,425,427],{"id":426},"результаты","Результаты",[179,429,430],{},"Теперь клиент может запустить полностью брендированное, готовое к публикации приложение кэшбэка для нового партнёра за долю того времени, что требовалось раньше, — не отвлекая инженеров от продуктовой работы под каждый запуск. Архитектура с общей кодовой базой держит 15+ приложений в едином ритме: одно исправление, одна функция, один релиз доходят до всех сразу. Админ-интерфейс превратил повторяющееся инженерное «узкое место» в возможность самообслуживания, а автоматизированный конвейер сделал каждый новый запуск предсказуемым и повторяемым событием, а не отдельным проектом. А офлайн-магазины, которые раньше работали вслепую, теперь сами проводят кампании кэшбэка и скидок и впервые знают, кто их клиенты.",[179,432,433],{},"Экономика в цифрах:",[286,435,436,442,448,454],{},[289,437,438,441],{},[199,439,440],{},"15+ работающих приложений из одной кодовой базы"," — без форков, без веток под отдельные бренды, без расхождений, которые пришлось бы сводить перед релизом.",[289,443,444,447],{},[199,445,446],{},"Предельная стоимость следующего брендированного приложения близка к нулю"," — новый бренд это конфигурационный бандл плюс метаданные для сторов, а не новый инженерный проект.",[289,449,450,453],{},[199,451,452],{},"Запуск бренда превратился из многодневной инженерной задачи в форму самообслуживания",", которой управляют менеджеры без навыков программирования.",[289,455,456,459],{},[199,457,458],{},"Единая кодовая база на Flutter обходится примерно на 30–40% дешевле двух нативных приложений"," — и поскольку на ней работает весь парк, эта экономия срабатывает заново с каждым брендом, накапливаясь по всем 15+ приложениям.",[179,461,462,463,467,468,472,473,423],{},"Именно такие платформы мы создаём в рамках ",[350,464,466],{"href":465},"\u002Fservices\u002Fwhitelabel-app-development","разработки white-label приложений"," — одна кодовая база на Flutter, на которой работает целый парк брендированных приложений, — и этот проект стал опорным для направления лояльности и кэшбэка в нашей практике ",[350,469,471],{"href":470},"\u002Fservices\u002Fflutter-app-development\u002Fe-commerce","разработки e-commerce приложений",". Админ-интерфейс, запускающий каждый бренд, — ровно тот внутренний бэк-офис, который описывает наша страница ",[350,474,476],{"href":475},"\u002Fservices\u002Fweb-development\u002Fadmin-dashboards","админ-панелей и дашбордов",[174,478,480],{"id":479},"faq","FAQ",[482,483],"questions",{":items":484},"[{\"title\":\"Что такое white-label платформа приложений?\",\"text\":\"Это единая кодовая база, которую можно ребрендировать и публиковать как любое число отдельных приложений с собственным фирменным стилем. На этой платформе флагманское приложение кэшбэка и каждое партнёрское приложение используют один и тот же Flutter-код; всё, что различается — цвета, логотипы, иконки, идентификаторы бандлов, фиче-флаги, конфигурация вознаграждений, метаданные для сторов, — выражено целиком через конфигурацию бренда, живущую вне кода.\"},{\"title\":\"Как одна кодовая база на Flutter может обслуживать больше 15 разных приложений?\",\"text\":\"Через систему flavor-ов и конфигураций: единый бинарный «чертёж» определяет фирменный стиль на этапе сборки из конфигурационного бандла конкретного приложения, а собственный инструментарий на Dart перезаписывает нативную конфигурацию сборки Android и iOS — записи Gradle, манифесты, Info.plist, каталоги ресурсов — под целевой бренд перед каждой сборкой. Ошибка, исправленная один раз, или функция, выпущенная один раз, попадает во все приложения парка в следующем релизе.\"},{\"title\":\"Как новое брендированное приложение запускается без разработчиков?\",\"text\":\"Через внутренний админ-интерфейс. Менеджер заполняет форму — название бренда, тема, иконки, цвета, метаданные для сторов, набор функций — а система генерирует конфигурационный бандл, регистрирует новое приложение в CI-конвейере и выпускает подписанные артефакты для iOS и Android. Затем Fastlane публикует каждое приложение в App Store и Google Play вместе с метаданными и скриншотами, поэтому релиз всего парка — это единая повторяемая операция.\"},{\"title\":\"Не отклоняют ли сторы white-label приложения?\",\"text\":\"Они отклоняют парки тонких, почти одинаковых «перекрасок» — именно для этого существует правило 4.2.6 у Apple. White-label платформа должна изначально проектироваться так, чтобы проходить ревью: каждое приложение в этом парке — полноценный брендированный продукт с собственной идентичностью, листингом в сторе и настроенным под бренд набором функций и вознаграждений, а не шаблон с заменённым логотипом. Конвейер публикации также поддерживает отдельные аккаунты разработчика для брендов, когда этого требуют партнёрские соглашения или политика стора.\"},{\"title\":\"Сколько стоит парк white-label приложений по сравнению с отдельными приложениями?\",\"text\":\"Первое приложение несёт стоимость платформы — общей кодовой базы, системы тем и фиче-флагов, движка правил, админ-панели и автоматизированного конвейера. Каждое следующее приложение обходится радикально дешевле, потому что новый бренд — это конфигурация, а не проект. Вдобавок единая кодовая база на Flutter обходится примерно на 30–40% дешевле, чем поддержка отдельных нативных приложений для iOS и Android, и эта экономия накапливается по всему парку.\"},{\"title\":\"Как бонус за приглашение переживает то, что приложение ещё не установлено?\",\"text\":\"Через отложенный deep linking, построенный на штатных механизмах платформ: лёгкий iOS App Clip перехватывает ссылку-приглашение до того, как существует полное приложение, и передаёт её через общий контейнер App Group, а на Android полезную нагрузку несёт Google Play Install Referrer API. Очередь отложенных ссылок удерживает приглашение, пока новый клиент не установит приложение, не зарегистрируется и не войдёт в аккаунт, — только тогда реферал атрибутируется и бонус начисляется обеим сторонам.\"}]",{"title":486,"searchDepth":487,"depth":487,"links":488},"",2,[489,490,491,492,493,494,495,496,497,498,499],{"id":176,"depth":487,"text":177},{"id":218,"depth":487,"text":219},{"id":246,"depth":487,"text":247},{"id":269,"depth":487,"text":270},{"id":276,"depth":487,"text":277},{"id":312,"depth":487,"text":313},{"id":344,"depth":487,"text":345},{"id":376,"depth":487,"text":377},{"id":387,"depth":487,"text":388},{"id":426,"depth":487,"text":427},{"id":479,"depth":487,"text":480},[501,502,503],"mobile","backend","web","nda","2025-08-01","White-label платформа кэшбэка и лояльности для офлайн-магазинов — 15+ брендированных приложений из одной Flutter-кодовой базы, приложение для мерчантов с настройкой собственных правил кэшбэка (день рождения, приглашение, кэшбэк за покупку) и админ-интерфейс, который запускает новые брендированные приложения автоматически.","8 месяцев","md",{"alt":510,"url":511},"Платформа кэшбэка и лояльности: визуальные материалы скрыты по NDA","\u002Fprojects\u002Fcashback-loyalty-platform\u002Fhero.webp",null,{},"White-label платформа кэшбэка и лояльности: 15+ брендированных приложений из одной Flutter-базы, приложение для мерчантов и админ-панель с автозапуском.",true,"Одна кодовая база на Flutter, 15+ брендированных приложений и админка, которая запускает новое сама. Плюс приложение для мерчантов с правилами кэшбэка.","\u002Fportfolio\u002Fcashback-loyalty-platform",{"title":169,"description":506},"cashback-loyalty-platform","portfolio\u002Fcashback-loyalty-platform",[41,18,155,90,160,95,100,121,35],"2026-09-05","rFA1cz2LTQyk1eQrC5HalLZv0ctZO-EvpY8kJUgmFk0",[525,540,552,567,580,595,611,624,637,654,667,678,688,701,713,724,733,747,760,767,780,795,808,821,834,845,856,867,880,890,903,915,929,940,954,963,974,987,1000,1013,1026,1038,1050,1062,1074,1086,1097,1111,1122,1134,1145,1158,1170],{"slug":526,"term":527,"definition":528,"category":529,"aliases":530,"links":532,"related":536,"readMore":-1,"target":538,"hasArticle":539},"aosp","AOSP","Android Open Source Project — Android без надстройки Google, который может форкнуть кто угодно. На его форках работают кассовые терминалы, киоски и автомобильные системы, а работа на этом уровне открывает части ОС, которых прикладной разработчик не видит.","platform",[531],"Android Open Source Project",[533],{"kind":534,"url":535},"website","https:\u002F\u002Fsource.android.com\u002F",[537],"host-card-emulation","\u002Fglossary#aosp",false,{"slug":541,"term":542,"definition":543,"category":529,"aliases":544,"links":545,"related":549,"readMore":-1,"target":551,"hasArticle":539},"app-clips","App Clips","Функция Apple, позволяющая запустить небольшую часть iOS-приложения — до 15 МБ — не устанавливая его целиком. Вызывается по QR-коду, NFC-метке или ссылке: для случаев, когда первое действие пользователя не должно требовать похода в App Store.",[],[546],{"kind":547,"url":548},"documentation","https:\u002F\u002Fdeveloper.apple.com\u002Fapp-clips\u002F",[398,550],"install-referrer","\u002Fglossary#app-clips",{"slug":553,"term":554,"definition":555,"category":529,"aliases":556,"links":557,"related":563,"readMore":-1,"target":566,"hasArticle":539},"bigquery","BigQuery","Аналитическое хранилище Google Cloud. Вы запускаете SQL по миллиардам строк, и они сканируются за секунды, а данные при этом лежат отдельно от машин, выполняющих запросы. Именно это снимает отчётность и исследование данных с базы, обслуживающей живой трафик.",[],[558,560],{"kind":534,"url":559},"https:\u002F\u002Fcloud.google.com\u002Fbigquery",{"kind":561,"url":562},"wikipedia","https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FBigQuery",[564,565],"object-storage","elasticsearch","\u002Fglossary#bigquery",{"slug":334,"term":568,"definition":569,"category":570,"aliases":571,"links":575,"related":578,"readMore":-1,"target":579,"hasArticle":539},"CI\u002FCD","Автоматизация, которая собирает, тестирует и выкладывает каждое изменение без ручного запуска команд. В мобильной разработке это то, что превращает релиз в нажатие кнопки вместо полудня ожидания, пока освободится нужный человек.","practice",[572,573,574],"CI","непрерывная интеграция","непрерывная поставка",[576],{"kind":561,"url":577},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCI\u002FCD",[],"\u002Fglossary#ci-cd",{"slug":581,"term":582,"definition":583,"category":584,"aliases":585,"links":588,"related":591,"readMore":-1,"target":594,"hasArticle":539},"crud","CRUD","Create, read, update, delete — четыре операции, стоящие почти за каждой формой и админкой. Собирательное название для рутинной половины приложения, которая управляет данными, в отличие от частей с реальной предметной логикой.","architecture",[586,587],"Create, Read, Update, Delete","создание, чтение, обновление, удаление",[589],{"kind":561,"url":590},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FCreate,_read,_update_and_delete",[592,593],"rest","graphql","\u002Fglossary#crud",{"slug":596,"term":597,"definition":598,"category":570,"aliases":599,"links":603,"related":608,"readMore":-1,"target":610,"hasArticle":539},"dev-container","Dev Container","Среда разработки, описанная один раз в devcontainer.json — ОС, инструменты и версии рантаймов, которые нужны проекту, — и открываемая одинаково внутри контейнера в редакторе любого участника, вместо инструкции по установке, которую каждый понимает по-своему.",[600,601,602],"devcontainer.json","Dev Containers","VS Code Dev Containers",[604,606],{"kind":534,"url":605},"https:\u002F\u002Fcontainers.dev\u002F",{"kind":547,"url":607},"https:\u002F\u002Fcode.visualstudio.com\u002Fdocs\u002Fdevcontainers\u002Fcontainers",[609],"container-registry","\u002Fglossary#dev-container",{"slug":565,"term":612,"definition":613,"category":529,"aliases":614,"links":617,"related":622,"readMore":-1,"target":623,"hasArticle":539},"Elasticsearch","Поисковый и аналитический движок, который индексирует записи, чтобы их можно было интерактивно фильтровать и искать, а не сканировать. К нему обращаются, когда вопрос звучит как «покажи вот эти сессии с шестью фильтрами», а не «просуммируй колонку».",[615,616],"Elastic","ELK",[618,620],{"kind":534,"url":619},"https:\u002F\u002Fwww.elastic.co\u002Felasticsearch",{"kind":561,"url":621},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FElasticsearch",[553],"\u002Fglossary#elasticsearch",{"slug":625,"term":626,"definition":627,"category":584,"aliases":628,"links":631,"related":632,"readMore":-1,"target":636,"hasArticle":539},"fan-out","Fan-out","Чтение источника один раз и доставка каждого обновления всем подписанным на него клиентам. Наивная версия пишет подписчикам в цикле и встаёт, как только один из сокетов начинает тормозить; рабочая — держит отдельный буфер на каждого клиента и отключает тех, кто не успевает.",[629,630],"веерная рассылка","фан-аут",[],[633,634,635],"websocket","pub-sub","server-sent-events","\u002Fglossary#fan-out",{"slug":638,"term":639,"definition":640,"category":570,"aliases":641,"links":644,"related":649,"readMore":-1,"target":653,"hasArticle":539},"gdpr","GDPR","Регламент ЕС о персональных данных людей в ЕС: законное основание для сбора, настоящее согласие на трекинг, право увидеть и удалить свои данные. Он следует за вашими пользователями, а не за вашими серверами: где зарегистрирована компания, значения не имеет.",[642,643],"Общий регламент по защите данных","General Data Protection Regulation",[645,647],{"kind":534,"url":646},"https:\u002F\u002Fgdpr.eu\u002F",{"kind":561,"url":648},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FGeneral_Data_Protection_Regulation",[650,651,652],"pci-dss","soc-2","hipaa","\u002Fglossary#gdpr",{"slug":655,"term":656,"definition":657,"category":570,"aliases":658,"links":662,"related":665,"readMore":-1,"target":666,"hasArticle":539},"golden-test","Golden-тест","Тест, который отрисовывает виджет и сравнивает результат попиксельно с эталонным изображением. Во Flutter это самый дешёвый способ узнать, не сломал ли редизайн пустое состояние на 320pt, в тёмной теме, при 200% масштабе текста.",[659,660,661],"golden test","золотой тест","скриншотный тест",[663],{"kind":547,"url":664},"https:\u002F\u002Fapi.flutter.dev\u002Fflutter\u002Fflutter_test\u002FmatchesGoldenFile.html",[334],"\u002Fglossary#golden-test",{"slug":593,"term":668,"definition":669,"category":584,"aliases":670,"links":671,"related":676,"readMore":-1,"target":677,"hasArticle":539},"GraphQL","Язык запросов к API, где клиент сам перечисляет нужные поля и получает один ответ ровно такой формы. Он снимает избыточную выдачу, к которой дрейфуют REST-эндпоинты, и добавляет собственный режим отказа: неограниченный запрос, обходящий всю модель данных.",[],[672,674],{"kind":534,"url":673},"https:\u002F\u002Fgraphql.org\u002F",{"kind":561,"url":675},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FGraphQL",[592],"\u002Fglossary#graphql",{"slug":652,"term":679,"definition":680,"category":570,"aliases":681,"links":683,"related":686,"readMore":-1,"target":687,"hasArticle":539},"HIPAA","Закон США о защищённой медицинской информации: как её можно хранить, передавать, логировать и раскрывать. Как и PCI-DSS, это архитектурное ограничение, которое выбирают в начале, а не документ, который дописывают перед запуском.",[682],"Health Insurance Portability and Accountability Act",[684],{"kind":561,"url":685},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHealth_Insurance_Portability_and_Accountability_Act",[650,638,651],"\u002Fglossary#hipaa",{"slug":689,"term":690,"definition":691,"category":584,"aliases":692,"links":695,"related":698,"readMore":-1,"target":700,"hasArticle":539},"headless-cms","Headless CMS","Система управления контентом с админкой и API, но без собственного фронтенда. Редакторы публикуют в одном месте, а сайт или приложение отрисовывает контент само — слой представления принадлежит вам, а не вендору CMS.",[693,694],"безголовая CMS","контентное API",[696],{"kind":561,"url":697},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FHeadless_content_management_system",[699,592],"server-side-rendering","\u002Fglossary#headless-cms",{"slug":537,"term":702,"definition":703,"category":529,"aliases":704,"links":708,"related":711,"readMore":-1,"target":712,"hasArticle":539},"Host Card Emulation","Режим, в котором Android-телефон программно эмулирует бесконтактную карту по NFC, без аппаратного защищённого элемента. Так платит приложение-кошелёк на терминале: телефон говорит с ним по тому же протоколу EMV Contactless, что и пластиковая карта.",[705,706,707],"HCE","EMV Contactless","бесконтактные платежи",[709],{"kind":547,"url":710},"https:\u002F\u002Fdeveloper.android.com\u002Fdevelop\u002Fconnectivity\u002Fnfc\u002Fhce",[650,526],"\u002Fglossary#host-card-emulation",{"slug":714,"term":715,"definition":716,"category":529,"aliases":717,"links":718,"related":721,"readMore":-1,"target":723,"hasArticle":539},"impeller","Impeller","Движок рендеринга, на котором Flutter работает сегодня: по умолчанию на iOS с 2023 года и на Android с 2024-го. Он компилирует шейдеры заранее, а не во время первой анимации, что убрало главную видимую проблему Flutter в проде — джанк на компиляции шейдеров.",[],[719],{"kind":547,"url":720},"https:\u002F\u002Fdocs.flutter.dev\u002Fperf\u002Fimpeller",[722],"skia","\u002Fglossary#impeller",{"slug":550,"term":725,"definition":726,"category":529,"aliases":727,"links":728,"related":731,"readMore":-1,"target":732,"hasArticle":539},"Install Referrer","API Google Play, который передаёт только что установленному Android-приложению параметры кампании из ссылки, приведшей к установке. Android-половина отложенного диплинкинга и надёжный способ понять, откуда пришёл пользователь.",[],[729],{"kind":547,"url":730},"https:\u002F\u002Fdeveloper.android.com\u002Fgoogle\u002Fplay\u002Finstallreferrer",[398,541],"\u002Fglossary#install-referrer",{"slug":734,"term":735,"definition":736,"category":737,"aliases":738,"links":740,"related":745,"readMore":-1,"target":746,"hasArticle":539},"jwt","JWT","Подписанный токен, несущий свои данные внутри: сервер понимает, кому принадлежит запрос, не обращаясь к хранилищу сессий. Стандарт мобильной аутентификации. Подпись доказывает, что токен не меняли, но не скрывает его содержимое.","protocol",[739],"JSON Web Token",[741,743],{"kind":534,"url":742},"https:\u002F\u002Fjwt.io\u002F",{"kind":561,"url":744},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FJSON_Web_Token",[650],"\u002Fglossary#jwt",{"slug":748,"term":749,"definition":750,"category":570,"aliases":751,"links":755,"related":758,"readMore":-1,"target":759,"hasArticle":539},"kyc","KYC","Know Your Customer — проверки личности, которые регулируемый финансовый продукт проводит, прежде чем разрешить переводить деньги: съёмка документов, liveness, санкционный и антиотмывочный скрининг. На онбординг это влияет сильнее любого дизайн-решения.",[752,753,754],"Know Your Customer","AML","KYC\u002FAML",[756],{"kind":561,"url":757},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FKnow_your_customer",[650,638],"\u002Fglossary#kyc",{"slug":76,"term":74,"definition":761,"category":529,"aliases":762,"links":764,"related":765,"readMore":766,"target":766,"hasArticle":539},"Переиспользование бизнес-логики на Kotlin между Android, iOS и сервером, при этом интерфейс на каждой платформе остаётся нативным. Альтернатива Flutter, когда UI обязан быть нативным, а правила за ним — нет.",[763],"KMP",[],[],"\u002Ftechnologies\u002Fkmp",{"slug":768,"term":769,"definition":770,"category":771,"aliases":772,"links":775,"related":778,"readMore":-1,"target":779,"hasArticle":539},"mvp","MVP","Минимальная версия продукта, которую можно показать реальным пользователям и которая при этом отвечает на вопрос, ради которого его делали. Решение об объёме, а не о качестве: MVP всё равно обязан работать.","business",[773,774],"минимально жизнеспособный продукт","minimum viable product",[776],{"kind":561,"url":777},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMinimum_viable_product",[193],"\u002Fglossary#mvp",{"slug":781,"term":782,"definition":783,"category":737,"aliases":784,"links":788,"related":793,"readMore":-1,"target":794,"hasArticle":539},"oauth","OAuth","Стандарт, на котором держатся «Вход через Apple», Google и остальные: пользователь авторизует ваше приложение у провайдера, которому уже доверяет, а приложение получает токен вместо пароля. Никто не заводит новый пароль, и вы его не храните.",[785,786,787],"OAuth 2.0","вход через соцсети","Sign in with Apple",[789,791],{"kind":534,"url":790},"https:\u002F\u002Foauth.net\u002F2\u002F",{"kind":561,"url":792},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FOAuth",[734],"\u002Fglossary#oauth",{"slug":650,"term":796,"definition":797,"category":570,"aliases":798,"links":801,"related":806,"readMore":-1,"target":807,"hasArticle":539},"PCI-DSS","Стандарт безопасности карточной индустрии, обязательный для всех, кто хранит, обрабатывает или передаёт данные карт. Большинство приложений намеренно остаются вне зоны его действия, отдавая ввод карты сертифицированному платёжному провайдеру.",[799,800],"PCI DSS","Payment Card Industry Data Security Standard",[802,804],{"kind":534,"url":803},"https:\u002F\u002Fwww.pcisecuritystandards.org\u002F",{"kind":561,"url":805},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FPayment_Card_Industry_Data_Security_Standard",[734],"\u002Fglossary#pci-dss",{"slug":809,"term":810,"definition":811,"category":771,"aliases":812,"links":815,"related":818,"readMore":-1,"target":820,"hasArticle":539},"product-market-fit","Product-market fit","Момент, когда продукт доказуемо нашёл своих людей: они им пользуются, возвращаются и платят. До него разработка отвечает на вопрос, после — на спрос.",[813,814],"PMF","соответствие продукта рынку",[816],{"kind":561,"url":817},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FProduct-market_fit",[768,819],"time-to-market","\u002Fglossary#product-market-fit",{"slug":822,"term":823,"definition":824,"category":570,"aliases":825,"links":828,"related":831,"readMore":-1,"target":833,"hasArticle":539},"prompt-injection","Prompt injection","Атака, при которой текст от пользователя языковая модель читает как инструкции, а не как данные, и уходит в обход собственных правил. Родственник SQL-инъекции в эпоху LLM: возникает везде, где пользовательский ввод склеивается в промпт.",[826,827],"инъекция промпта","инъекция в промпт",[829],{"kind":561,"url":830},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FPrompt_injection",[832],"rate-limiting","\u002Fglossary#prompt-injection",{"slug":634,"term":835,"definition":836,"category":584,"aliases":837,"links":840,"related":843,"readMore":-1,"target":844,"hasArticle":539},"Pub\u002FSub","Шаблон обмена сообщениями: производитель публикует событие, а любое число потребителей независимо читает его через стоящий между ними брокер. Производитель никогда их не ждёт — так путь запроса остаётся быстрым, а более медленная работа выполняется в фоне.",[838,839],"публикация\u002Fподписка","Google Cloud Pub\u002FSub",[841],{"kind":561,"url":842},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FPublish%E2%80%93subscribe_pattern",[],"\u002Fglossary#pub-sub",{"slug":592,"term":846,"definition":847,"category":584,"aliases":848,"links":851,"related":854,"readMore":-1,"target":855,"hasArticle":539},"REST","Общепринятый стиль HTTP-API: URL называет ресурс, а HTTP-метод говорит, что с ним сделать. Способ по умолчанию, которым приложение общается с бэкендом, и то, что ожидает найти большинство сторонних интеграций.",[849,850],"REST API","Representational State Transfer",[852],{"kind":561,"url":853},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FREST",[633,635],"\u002Fglossary#rest",{"slug":651,"term":857,"definition":858,"category":570,"aliases":859,"links":862,"related":865,"readMore":-1,"target":866,"hasArticle":539},"SOC 2","Отчёт внешнего аудитора о том, как компания обращается с данными клиентов — безопасность, доступность, конфиденциальность, — а не сертификат, который можно купить. Корпоративные заказчики его требуют, а архитектуру он ограничивает задолго до самого аудита.",[860,861],"SOC2","System and Organization Controls",[863],{"kind":561,"url":864},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSystem_and_Organization_Controls",[650,638,652],"\u002Fglossary#soc-2",{"slug":868,"term":869,"definition":870,"category":771,"aliases":871,"links":874,"related":877,"readMore":-1,"target":879,"hasArticle":539},"saas","SaaS","Софт, который продают как постоянную подписку на размещённый у поставщика продукт, а не как разовую лицензию для установки у себя. Поставщик держит серверы, непрерывно выкатывает обновления и берёт плату за пользователя или за объём.",[872,873],"Software as a Service","ПО как услуга",[875],{"kind":561,"url":876},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSoftware_as_a_service",[878,193],"multi-tenancy","\u002Fglossary#saas",{"slug":635,"term":881,"definition":882,"category":737,"aliases":883,"links":885,"related":888,"readMore":-1,"target":889,"hasArticle":539},"Server-Sent Events","Односторонний поток от сервера к клиенту поверх обычного HTTP-соединения. Проще, чем WebSocket, и достаточен там, где только серверу есть что сказать: прогресс операции, ответ AI, приходящий токен за токеном.",[884],"SSE",[886],{"kind":561,"url":887},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FServer-sent_events",[633,592],"\u002Fglossary#server-sent-events",{"slug":722,"term":891,"definition":892,"category":529,"aliases":893,"links":896,"related":901,"readMore":-1,"target":902,"hasArticle":539},"Skia","Открытая 2D-графическая библиотека Google, которая рисует Chrome, Android и — до появления Impeller — каждый кадр Flutter. Она умеет выводить не только на экран, но и в PDF: именно это делает «печать в PDF» в Chrome.",[894,895],"Skia Graphics Engine","skia-safe",[897,899],{"kind":534,"url":898},"https:\u002F\u002Fskia.org\u002F",{"kind":561,"url":900},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FSkia_Graphics_Engine",[714],"\u002Fglossary#skia",{"slug":904,"term":905,"definition":906,"category":771,"aliases":907,"links":911,"related":912,"readMore":-1,"target":914,"hasArticle":539},"staff-augmentation","Staff augmentation","Модель найма, при которой инженеры внешнего партнёра входят в вашу команду и работают под вашим управлением — в вашем репозитории, ваших спринтах, вашем процессе, — а не сдают отдельный проект. Вы покупаете ресурс; код и контекст остаются у вас.",[908,909,910],"аутстаффинг","расширение команды","выделенные разработчики",[],[913,819],"total-cost-of-ownership","\u002Fglossary#staff-augmentation",{"slug":916,"term":917,"definition":918,"category":737,"aliases":919,"links":923,"related":926,"readMore":-1,"target":928,"hasArticle":539},"tls","TLS","Слой шифрования под HTTPS. Он подтверждает, что сервер именно тот, о ком говорит его сертификат, согласует свежий ключ на сессию и шифрует всё дальнейшее — сеть между вами видит шифртекст и не может незаметно его изменить.",[920,921,922],"SSL","HTTPS","Transport Layer Security",[924],{"kind":561,"url":925},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FTransport_Layer_Security",[927,734],"end-to-end-encryption","\u002Fglossary#tls",{"slug":819,"term":930,"definition":931,"category":771,"aliases":932,"links":935,"related":938,"readMore":-1,"target":939,"hasArticle":539},"Time to market","Время от решения строить продукт до момента, когда им пользуются настоящие люди. Большинство споров о стеке и объёме работ — на самом деле споры об этом числе: каждая сэкономленная неделя — это неделя выручки, обратной связи и позиции на рынке.",[933,934],"TTM","время выхода на рынок",[936],{"kind":561,"url":937},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FTime_to_market",[768,913],"\u002Fglossary#time-to-market",{"slug":941,"term":942,"definition":943,"category":737,"aliases":944,"links":946,"related":951,"readMore":-1,"target":953,"hasArticle":539},"webrtc","WebRTC","Браузерный и мобильный стандарт для передачи аудио, видео и данных напрямую между двумя устройствами; серверы участвуют только в том, чтобы их познакомить. На нём строят видеозвонок внутри приложения, когда не берут готовый SDK.",[945],"Web Real-Time Communication",[947,949],{"kind":534,"url":948},"https:\u002F\u002Fwebrtc.org\u002F",{"kind":561,"url":950},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FWebRTC",[952,633],"xmpp","\u002Fglossary#webrtc",{"slug":633,"term":955,"definition":956,"category":737,"aliases":957,"links":958,"related":961,"readMore":-1,"target":962,"hasArticle":539},"WebSocket","Протокол, который держит одно соединение между клиентом и сервером открытым, чтобы любая сторона могла отправить данные в любой момент, а не клиент спрашивал снова и снова. На нём работают живые котировки, чаты и статусы присутствия.",[],[959],{"kind":561,"url":960},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FWebSocket",[635,592],"\u002Fglossary#websocket",{"slug":193,"term":964,"definition":965,"category":771,"aliases":966,"links":969,"related":972,"readMore":973,"target":973,"hasArticle":515},"White-label","Один продукт, выпускаемый под многими брендами. White-label платформа собирает каждому клиенту готовое к публикации приложение со своим названием, оформлением и контентом из общей кодовой базы, а не форкает проект под заказчика.",[967,968],"белый лейбл","мультитенантное приложение",[970],{"kind":561,"url":971},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FWhite-label_product",[768],"\u002Fglossary\u002Fwhite-label",{"slug":952,"term":975,"definition":976,"category":737,"aliases":977,"links":980,"related":985,"readMore":-1,"target":986,"hasArticle":539},"XMPP","Открытый федеративный протокол обмена сообщениями и давняя альтернатива тому, чтобы писать чат-бэкенд самому или арендовать чужой. Он покрывает статусы присутствия, индикаторы набора и передачу файлов, а зрелые клиентские библиотеки есть под любую платформу.",[978,979],"Jabber","Extensible Messaging and Presence Protocol",[981,983],{"kind":534,"url":982},"https:\u002F\u002Fxmpp.org\u002F",{"kind":561,"url":984},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FXMPP",[941,633],"\u002Fglossary#xmpp",{"slug":988,"term":989,"definition":990,"category":771,"aliases":991,"links":995,"related":998,"readMore":-1,"target":999,"hasArticle":539},"in-app-purchase","Встроенные покупки","Продажа цифровых товаров и подписок через биллинг Apple и Google, который оба стора требуют для цифрового контента и с которого берут комиссию. Сложность никогда не в самой покупке, а в её восстановлении на новом устройстве и в честном учёте прав доступа.",[992,993,994],"in-app purchase","IAP","внутренние покупки",[996],{"kind":547,"url":997},"https:\u002F\u002Fdeveloper.apple.com\u002Fin-app-purchase\u002F",[809],"\u002Fglossary#in-app-purchase",{"slug":398,"term":1001,"definition":1002,"category":529,"aliases":1003,"links":1008,"related":1011,"readMore":1012,"target":1012,"hasArticle":515},"Диплинкинг","Ссылка, которая открывает конкретный экран внутри установленного приложения, а не его главную или веб-страницу. Отложенный диплинкинг переживает установку: нажатие, прошедшее через магазин приложений, всё равно приводит на нужный экран.",[1004,1005,1006,1007],"deep linking","отложенный диплинкинг","Universal Links","Android App Links",[1009],{"kind":561,"url":1010},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMobile_deep_linking",[541,550],"\u002Fglossary\u002Fdeep-linking",{"slug":1014,"term":1015,"definition":1016,"category":584,"aliases":1017,"links":1021,"related":1024,"readMore":-1,"target":1025,"hasArticle":539},"multi-arch-image","Мультиархитектурный образ","Один тег образа, который разрешается в разные бинарники для каждой архитектуры процессора — обычно это пара linux\u002Famd64 и linux\u002Farm64, — так что один и тот же docker pull работает без изменений и на серверах Intel\u002FAMD, и на ноутбуках с Apple Silicon.",[1018,1019,1020],"мультиарх-сборка","multi-arch build","linux\u002Famd64 + linux\u002Farm64",[1022],{"kind":547,"url":1023},"https:\u002F\u002Fdocs.docker.com\u002Fbuild\u002Fbuilding\u002Fmulti-platform\u002F",[609],"\u002Fglossary#multi-arch-image",{"slug":878,"term":1027,"definition":1028,"category":584,"aliases":1029,"links":1032,"related":1035,"readMore":-1,"target":1037,"hasArticle":539},"Мультитенантность","Один развёрнутый бэкенд обслуживает много клиентов, и каждый видит только свои данные, конфигурацию и включённые функции, потому что контекст тенанта определяется для каждого запроса. Именно это делает линейку брендированных приложений одним продуктом, а не набором форков.",[878,1030,1031],"мультиарендность","тенант",[1033],{"kind":561,"url":1034},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FMultitenancy",[193,1036],"feature-flags","\u002Fglossary#multi-tenancy",{"slug":564,"term":1039,"definition":1040,"category":584,"aliases":1041,"links":1045,"related":1048,"readMore":-1,"target":1049,"hasArticle":539},"Объектное хранилище","Хранилище, которое держит файл целиком под ключом, а не в дереве файловой системы, — Amazon S3 и множество сервисов, совместимых с его API. Дешёвое, практически безграничное, привычное место для сырых событий, бэкапов и медиа: пишется один раз, читается редко, хранится вечно.",[1042,1043,1044],"S3","S3-совместимое хранилище","блоб-хранилище",[1046],{"kind":561,"url":1047},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FObject_storage",[553],"\u002Fglossary#object-storage",{"slug":832,"term":1051,"definition":1052,"category":570,"aliases":1053,"links":1057,"related":1060,"readMore":-1,"target":1061,"hasArticle":539},"Ограничение частоты запросов","Предел на число запросов от одного клиента за заданный интервал. Именно он не даёт одному увлечённому пользователю, скраперу или боту потратить месячный бюджет платного API за вечер, и стоять он должен на вашей стороне интеграции.",[1054,1055,1056],"rate limiting","рейт-лимит","троттлинг",[1058],{"kind":561,"url":1059},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FRate_limiting",[822],"\u002Fglossary#rate-limiting",{"slug":1063,"term":1064,"definition":1065,"category":529,"aliases":1066,"links":1069,"related":1072,"readMore":-1,"target":1073,"hasArticle":539},"platform-channels","Платформенные каналы","Мост, через который Flutter-приложение вызывает нативный код iOS и Android — Keychain и Keystore, биометрию, платёжные шторки, любой SDK без Dart-пакета. Работа рутинная, но настоящая, и первое место, где споткнётся инженер, не выходивший за пределы Dart.",[1067,1068],"platform channels","method channel",[1070],{"kind":547,"url":1071},"https:\u002F\u002Fdocs.flutter.dev\u002Fplatform-integration\u002Fplatform-channels",[76],"\u002Fglossary#platform-channels",{"slug":1075,"term":1076,"definition":1077,"category":737,"aliases":1078,"links":1081,"related":1084,"readMore":-1,"target":1085,"hasArticle":539},"post-quantum-cryptography","Постквантовая криптография","Алгоритмы шифрования, рассчитанные на устойчивость к будущему квантовому компьютеру; стандарты уже финализированы NIST. Мигрировать нужно до появления железа: трафик, записанный сегодня, расшифруют, когда такая машина появится.",[1079,1080],"PQC","постквантовое шифрование",[1082],{"kind":561,"url":1083},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FPost-quantum_cryptography",[916,927],"\u002Fglossary#post-quantum-cryptography",{"slug":1087,"term":1088,"definition":1089,"category":570,"aliases":1090,"links":1094,"related":1095,"readMore":-1,"target":1096,"hasArticle":539},"staged-rollout","Поэтапная раскатка","Релиз сначала на небольшой процент пользователей и расширение только тогда, когда доля сессий без падений держится. Плохая сборка, пойманная на десяти процентах, — испорченный вечер; она же на ста процентах — испорченная неделя.",[1091,1092,1093],"staged rollout","phased release","канареечный релиз",[],[1036,334],"\u002Fglossary#staged-rollout",{"slug":609,"term":1098,"definition":1099,"category":584,"aliases":1100,"links":1106,"related":1109,"readMore":-1,"target":1110,"hasArticle":539},"Реестр контейнеров","Хранилище образов контейнеров, адресуемых по имени и тегу, — Docker Hub, GitHub Container Registry или собственный реестр облачного провайдера. Публикация сборки в реестр превращает «у меня работает» в образ, который любой может скачать и запустить без изменений.",[1101,1102,1103,1104,1105],"реестр образов","Docker registry","GHCR","ghcr.io","container registry",[1107],{"kind":547,"url":1108},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Fpackages\u002Fworking-with-a-github-packages-registry\u002Fworking-with-the-container-registry",[596,1014],"\u002Fglossary#container-registry",{"slug":699,"term":1112,"definition":1113,"category":584,"aliases":1114,"links":1117,"related":1120,"readMore":-1,"target":1121,"hasArticle":539},"Серверный рендеринг","Сборка страницы в готовый HTML на сервере, чтобы первый же ответ содержал контент, заголовки, метатеги и структурированные данные. Краулеры, превью ссылок и медленные устройства читают это, не выполняя JavaScript.",[1115,1116],"SSR","server-side rendering",[1118],{"kind":561,"url":1119},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FServer-side_scripting",[689],"\u002Fglossary#server-side-rendering",{"slug":927,"term":1123,"definition":1124,"category":584,"aliases":1125,"links":1129,"related":1132,"readMore":-1,"target":1133,"hasArticle":539},"Сквозное шифрование","Шифрование, которое накладывается на устройстве отправителя и снимается только на устройстве получателя, так что сервис, передающий сообщение, не может его прочитать — ни по решению суда, ни после взлома. Оно защищает содержимое, но никогда — метаданные.",[1126,1127,1128],"E2EE","end-to-end encryption","оконечное шифрование",[1130],{"kind":561,"url":1131},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FEnd-to-end_encryption",[916,734],"\u002Fglossary#end-to-end-encryption",{"slug":913,"term":1135,"definition":1136,"category":771,"aliases":1137,"links":1140,"related":1143,"readMore":-1,"target":1144,"hasArticle":539},"Совокупная стоимость владения","Во что продукт обходится за всю жизнь, а не только на этапе разработки: поддержка, обновления, ежегодные миграции на новые ОС и правила сторов, вторая команда, чтобы две кодовые базы не расходились. Обычно больше сметы на разработку и почти никогда в неё не входит.",[1138,1139],"TCO","total cost of ownership",[1141],{"kind":561,"url":1142},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FTotal_cost_of_ownership",[819],"\u002Fglossary#total-cost-of-ownership",{"slug":1146,"term":1147,"definition":1148,"category":584,"aliases":1149,"links":1153,"related":1156,"readMore":-1,"target":1157,"hasArticle":539},"state-management","Управление состоянием","То, как приложение решает, где живёт значение, кому позволено его менять и какие части экрана перерисовываются, когда оно меняется. Во Flutter выбор между Riverpod, BLoC и Provider — одно из первых архитектурных решений и одно из самых трудных для пересмотра.",[1150,1151,1152],"state management","BLoC","Riverpod",[1154],{"kind":547,"url":1155},"https:\u002F\u002Fdocs.flutter.dev\u002Fdata-and-backend\u002Fstate-mgmt\u002Foptions",[655],"\u002Fglossary#state-management",{"slug":1036,"term":1159,"definition":1160,"category":570,"aliases":1161,"links":1165,"related":1168,"readMore":-1,"target":1169,"hasArticle":539},"Фиче-флаги","Переключатели, которые включают и выключают функциональность из конфигурации, а не из релиза. Один бинарник ведёт себя по-разному для разных брендов, рынков и пользователей, а рискованную фичу можно погасить, не отправляя новую сборку на ревью.",[1162,1163,1164],"feature flags","фиче-флаги","feature toggle",[1166],{"kind":561,"url":1167},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FFeature_toggle",[1087,193,878],"\u002Fglossary#feature-flags",{"slug":1171,"term":1172,"definition":1173,"category":584,"aliases":1174,"links":1178,"related":1181,"readMore":-1,"target":1182,"hasArticle":539},"floating-point","Числа с плавающей точкой","Двоичный формат IEEE 754, стоящий за double и float. Он не хранит 0.1 точно, поэтому 0.1 + 0.2 даёт 0.30000000000000004 — незаметно в графике и фатально в деньгах, которым место в целых минорных единицах или в decimal-типе.",[1175,1176,1177],"IEEE 754","double","плавающая запятая",[1179],{"kind":561,"url":1180},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FIEEE_754",[],"\u002Fglossary#floating-point"]