Source: https://docs.flipflag.ru/ai-integration # Интеграция с AI-инструментами Cursor, Claude, Codex и другие помощники могут интегрировать FlipFlag через документацию и SDK. Для этого не требуется отдельный MCP-сервер. - [Карта документации для агента](/llms.txt) - [Документация одним текстовым файлом](/llms-full.txt) - [Скачать skill интеграции](https://docs.flipflag.ru/skills/flipflag-integration/SKILL.md) Skill — Markdown с инструкциями. Подключите его по правилам вашего инструмента или дайте агенту прочитать файл как руководство проекта. Публикация файла сама по себе не устанавливает расширение в IDE. ## Пример задания агенту ```text Интегрируй FlipFlag в существующий React-проект. Прочитай https://docs.flipflag.ru/llms.txt и skill интеграции. API: https://api.flipflag.ru, окружение: prod. Ключ возьми из конфигурации приложения; не печатай его в отчёте. Для new_checkout безопасный default — false. Используй стабильный непрозрачный ID пользователя из текущей авторизации. Обновляй контекст при смене аккаунта и при logout. При недоступном API приложение должно продолжать работу. Проверь оба значения флага, холодный запуск без API и смену пользователя. ``` Для on-prem замените API на origin заказчика, например `https://flags.company.example`. Не добавляйте `/v1` к `url`: SDK добавляет путь. ## Что проверить при приёмке Ключ должен соответствовать проекту, окружению и платформе. Browser/mobile ключ видим пользователям; server key хранится только на сервере. Флаги не заменяют проверку прав доступа. Передавайте минимальные атрибуты пользователя. React `useFlag().enabled` описывает активность возвращённого флага; для boolean-решения проверяйте `value === true`. В Node/SSR контекст конкретного пользователя нельзя менять в общем singleton-клиенте для параллельных запросов. SDK выполняет удалённое вычисление и периодическое обновление, в JavaScript по умолчанию каждые 15 секунд. Чтение работает из последнего снимка; после ошибки обновления сохраняется последний успешный результат. При холодном запуске используется default приложения. Метрики отправляются best effort и не являются надёжным бухгалтерским учётом или доказательством MAU. Проверяйте установленную версию и доступность пакета в registry. Изменения в репозитории SDK могут появляться раньше, чем опубликованный npm-пакет. --- Source: https://docs.flipflag.ru/backend-contracts # Backend Contracts All SDKs evaluate flags by calling the backend. The SDK never performs local evaluation. Endpoints: - `POST /v1/sdk/flags/evaluate` - `POST /v1/sdk/metrics` The SDK uses `x-sdk-key` (SDK API key) on every request. ## Значения и правила флагов При создании boolean-флага без вариантов (или с `variations: []`) все пользователи получают `defaultValue`. Backend сохраняет явные веса 100/0. Для эксперимента задайте варианты с весами, например 50/50; все явные веса обязательны и в сумме должны давать 100. Ранее сохранённые варианты без весов продолжают распределяться равномерно, чтобы обновление сервера не изменяло существующие группы пользователей. `enabled: false` отключает вычисление правил и возвращает `defaultValue`. `enabled: true` включает правила; это само по себе не означает результат `true`. `targeting.fallthrough` применяется и при пустом списке правил. Форма админки использует JSON: `true` — boolean, `"true"` — строка, `123` — число, `"123"` — строка, `null`, массивы и объекты также поддерживаются. Сохранение существующего значения сохраняет его JSON-тип. Backend отклоняет некорректные правила, неизвестные операторы/варианты, rollout вне 0..100, повторяющиеся ключи и неверные веса. Лимиты: 128 KiB на конфигурацию, 100 вариантов, 100 правил и 50 условий в правиле. Для `in`/`not_in` нужен массив; для числового сравнения — число. SDK endpoints разрешают CORS с любого origin для `Content-Type` и `X-SDK-Key`, без cookies. Это позволяет встраивать SDK в сайт клиента. SDK-ключ в браузере доступен пользователю сайта: храните секреты в своём backend. Metadata содержит только `key`, `enabled`, `updatedAt` и не раскрывает условия таргетинга или значения. `GET /version` показывает commit работающего backend. `/readyz` в on-prem режиме проверяет control и tenant PostgreSQL; проверка лицензии доступна отдельно через `/v1/license/status`. ## SDK-ключи и безопасная ротация Администратор организации управляет ключами в Settings проекта: создаёт отдельный ключ для окружения и приложения, выбирает browser/mobile или server, задаёт срок действия и отзывает старые ключи. Новый ключ показывается при создании; список содержит только метаданные. Совместимый default-ключ по-прежнему можно скопировать в Settings. Ранее выпущенные legacy-ключи сохраняют доступ ко всем окружениям своего проекта, пока вы не замените и не отзовёте их. 1. Создайте новый ключ для нужного окружения. 2. Обновите секрет в приложении и разверните новую версию. 3. Проверьте получение флагов и статистику. 4. Отзовите старый ключ. Он сразу перестанет проходить авторизацию. `GET/POST /v1/projects/{projectId}/sdk-keys` — список и создание; `DELETE /v1/projects/{projectId}/sdk-keys/{keyId}` — отзыв. Эти операции доступны только администраторам организации. Истёкший или отозванный ключ получает 401; запрос к другому окружению — 403. Неизвестное окружение получает 404. Server-ключ отклоняет browser-запросы с `Origin`; это дополнительная защита от случайной публикации ключа, а не замена секретного хранения. В мобильном приложении ключ также можно извлечь — используйте тип browser/mobile. `Last used` отражает последнюю доставку метрик, а не все проверки флагов. В облаке обновление tenant-схемы выполняется при первом подключении организации с ограничением времени. Ошибка одного tenant не останавливает запуск всего API. CLI migrate и Helm Job проверяют все требуемые базы до развёртывания. Один tenant pool одной реплики API ограничен двумя соединениями; control pool — десятью. Это снижает расход соединений, но не заменяет PgBouncer и общее планирование лимитов PostgreSQL при увеличении количества организаций и реплик. ## Регистрация и обновления базы Публичная регистрация ограничена общим бюджетом `REGISTRATION_HOURLY_LIMIT` (по умолчанию 10 попыток в час) и тремя попытками на email в час. Бюджет хранится в PostgreSQL и действует для всех реплик; при превышении — 429. Новая tenant-база удаляется при подтверждённом откате регистрации; при неопределённом результате commit она сохраняется для проверки оператором. Старые аккаунты с одинаковым нормализованным email сохраняются при обновлении. Новые дубли запрещены, неоднозначный вход блокируется. Оператор должен сверить владельцев и согласовать смену адреса; миграция не выбирает аккаунт автоматически. В облаке базы арендаторов обновляются независимо при обращении. Первое обращение может получить 503 с `Retry-After: 30`, пока миграция выполняется. Тайм-аут HTTP-запроса не прерывает миграцию; на инициализацию отведено до пяти минут. Неудачная инициализация повторяется не чаще одного раза в 30 секунд. --- Source: https://docs.flipflag.ru/configuration # Configuration Configuration is consistent across all SDKs. Required: - `url` — Base API URL (example: `https://api.example.com`). - `sdkKey` — SDK API key (sent in `x-sdk-key`). - `context.userId` — Required user identifier for evaluations and metrics. Optional: - `env` — Environment name. Default: `prod`. - `refreshIntervalMs` — Polling interval for evaluations. Default: `15000`. - `metricsIntervalMs` — Metrics flush interval. Default: `60000`. - `disableRefresh` — Disable polling. Default: `false`. - `disableMetrics` — Disable metrics. Default: `false`. - `fetch` — Custom `fetch` implementation. Для self-host `url` — адрес вашей установки, например `https://flags.example.com`, без суффикса `/v1`. `sdkKey` — ключ проекта; ключ активации on-prem сюда не передаётся. Используйте HTTPS и рабочие defaults. [Порядок установки](https://docs.flipflag.ru/on-premise.mdx). --- Source: https://docs.flipflag.ru/core-api # Core API The `FlipFlagClient` is the shared client used by all SDKs. - `start(): Promise` — Starts polling and metrics timers. - `stop(): void` — Stops timers. - `isEnabled(flagKey: string, defaultValue?: boolean): boolean` - `getVariant(flagKey: string, defaultValue?: FlagValue): SdkFlagEvaluation` - `getAllFlags(): Record` - `updateContext(context: SdkContext): void` - `flushMetrics(): Promise` - `getStatus(): { ready: boolean; error?: Error; updatedAt?: string }` Events: - `ready` — initial evaluations fetched. - `update` — evaluations refreshed. - `error` — request failed. - `metrics` — metrics flushed. --- Source: https://docs.flipflag.ru/core-concepts # Core Concepts - The SDK polls `/v1/sdk/flags/evaluate` to keep evaluations up to date. - Evaluations contain `value`, `variationKey`, and `reason`. - Every flag evaluation can be sent as a metric event to `/v1/sdk/metrics`. - Context can be updated at runtime to re-evaluate flags. --- Source: https://docs.flipflag.ru/error-handling # Ошибки SDK и безопасные значения по умолчанию SDK не должен делать доступность всего приложения зависимой от сети FlipFlag. Запросы имеют таймаут; сетевой сбой, `401`, `402`, `429`, `5xx` или некорректный ответ не являются новым значением флага. | Состояние | Что возвращать приложению | |---|---| | Есть успешный снимок текущего контекста | Последнее полученное значение | | Флаг ещё не получен, удалён или кэш отсутствует | Явно заданный разработчиком default | | Изменился пользователь/контекст | Безопасный default до получения нового снимка | | Приложение/страница запущены заново | Default; кэш SDK находится в памяти | ```ts const useNewCheckout = client.isEnabled("new_checkout", false); // false ведёт к рабочему старому сценарию оформления заказа. ``` В React проверяйте `value === true`, если флаг булевый. Поле `enabled` у `useFlag` обозначает наличие активного флага, а не истинность его значения. Флаг с `value: false` может иметь `enabled: true`. ```tsx function Checkout() { const { value } = useFlag("new_checkout", false); const status = useFlagsStatus(); return <> {status.error && Настройки временно недоступны} {value === true ? : } ; } ``` `ready` означает успешную загрузку, а не окончание попытки запуска. Если первый запрос завершился ошибкой, `ready` может остаться `false`: не показывайте вечный spinner и не скрывайте всё приложение до успешной загрузки. JS `start()` завершает начальную попытку и при сетевой ошибке; ошибка доступна через `getStatus().error` и событие `error`. Android и Swift запускают запросы асинхронно. ## On-prem и HTTP 402 После окончания лицензии [on-prem API](https://docs.flipflag.ru/on-premise.mdx#продление-и-окончание-подписки) блокирует business endpoints, включая SDK evaluate/metrics, ответом **402 Payment Required**. Ранее полученные значения могут оставаться в SDK; без них используются defaults. Это не гарантирует неизменность поведения приложения: defaults и обработка ошибок должны быть предусмотрены его разработчиками. Данные БД при блокировке не удаляются. После оплаты и успешного обновления лицензии запросы снова обслуживаются. ## Контекст, метрики и эксплуатация Передавайте только необходимые `userId` и атрибуты: они входят в запросы к вашей установке FlipFlag и в метрики. Не отправляйте пароли, токены или лишние персональные данные. На сервере создавайте отдельный SDK-контекст для каждого запроса/пользователя; не переключайте одну общую Node.js инстанцию между параллельными пользователями. Метрики имеют ограниченный буфер в памяти и best-effort доставку. При сбое возможны потери и повторная доставка. Их нельзя использовать как единственный источник биллинга. Вызывайте `stop()` при завершении жизненного цикла клиента, Android `close()` — для окончательного освобождения ресурсов. Изменения подробной диагностики ошибок, сброса контекста и lifecycle находятся в [ветке аудита SDK](https://github.com/Mthu042/flipflag-sdk/tree/sdk-hardening-20261011); [инструкции по платформам](https://docs.flipflag.ru/index.mdx) должны сопоставляться с установленной версией пакета. Не считайте наличие текста в документации подтверждением публикации новой версии в npm/Maven. --- Source: https://docs.flipflag.ru/ # flipFeatureFlag SDK The flipFeatureFlag SDKs provide a unified API to evaluate feature flags from the flipFeatureFlag backend, collect usage metrics, and integrate with popular frameworks. JavaScript packages share a core; native Swift/Kotlin clients implement the same HTTP contract. ## Packages - `@flipfeatureflag/core` — Shared core client, types, HTTP, and metrics. - `@flipfeatureflag/js` — Browser SDK. - `@flipfeatureflag/react` — React Provider and hooks. - `@flipfeatureflag/next` — Next.js helpers plus React bindings. - `@flipfeatureflag/vue` — Vue plugin and composables. - `@flipfeatureflag/node` — Node.js SDK. - `@flipfeatureflag/react-native` — React Native Provider and hooks. - [Android / Kotlin](https://docs.flipflag.ru/sdk/android.mdx) — native Android client. - [iOS / Swift](https://docs.flipflag.ru/sdk/ios.mdx) — native Swift client. ## On-prem / Self-host Разверните FlipFlag в инфраструктуре компании: - [Установка одной командой через Docker Compose](https://docs.flipflag.ru/on-premise.mdx) — IP, HTTPS, корпоративный proxy, онлайн-активация и закрытая сеть. - [Kubernetes и Helm](https://docs.flipflag.ru/on-premise-kubernetes.mdx) — корпоративный PostgreSQL, Secrets, ingress, реплики и продление лицензии. SDK используют адрес вашей установки; ключ активации on-prem не является SDK-ключом проекта. --- Source: https://docs.flipflag.ru/metrics # Статистика использования флагов Раздел статистики показывает, какие флаги читали через SDK, какие варианты получали пользователи и как менялась активность. Это не число HTTP-запросов, не продуктовая аналитика и не точный счётчик MAU для выставления счетов. ## Что считается событием В JS/Core/Node, Kotlin и Swift каждый вызов `isEnabled` или `getVariant` для известного флага добавляет одно чтение. Два вызова — два чтения, даже если значение не изменилось. Получение конфигурации по сети само по себе чтением не считается. Отсутствующий флаг и локальный default до первой загрузки событий не создают. React, React Native и Vue hooks записывают использование после commit/mount, затем при изменении контекста или результата. Повторный рендер родителя и неизменившийся ответ опроса новых событий не добавляют. Два смонтированных hook считаются двумя использованиями. `useAllFlags` учитывает каждый изменившийся флаг отдельно. JS `getAllFlags()` создаёт по событию на каждый возвращённый флаг. Для просмотра без статистики используйте `peekAllFlags()`, `peekVariant()`, `hasFlag()` или `listFlagEvaluations()`. `track(key)` явно записывает чтение известного флага. ## Как читать показатели | Показатель | Значение | | --- | --- | | Чтения | Число принятых событий SDK за период | | Уникальные пользователи | Число разных `context.userId` среди принятых событий | | Варианты | Чтения и уникальные пользователи для пары `variationKey` / `reason` | | Динамика по дням | События по календарным дням UTC, включая нулевые дни | Используйте стабильный псевдонимный `userId`, одинаковый на разных устройствах одного пользователя. Пробелы по краям убираются; регистр имеет значение. Случайный ID на каждом старте завысит уникальных пользователей. Если Алиса прочитала два флага, каждый флаг покажет одного пользователя, а общий итог тоже одного. Уникальные показатели по флагам, вариантам и дням **не суммируются**. Охват за семь дней не является MAU за календарный месяц. Нет событий — значит события не получены; это не доказывает, что никто не пользовался приложением. В админке доступны последние 24 часа, 7 или 30 дней и свой период до 366 дней. Текущий период сдвигается и обновляется каждые 30 секунд, пока вкладка видима. Свой период фиксирован; его можно обновить кнопкой. Даты фильтра показаны в часовом поясе браузера, дневные группы — в UTC; крайние дни могут быть неполными. Начало входит в период, конец не входит: `[from, to)`. Ошибка загрузки показывается отдельно и не подменяется нулевыми значениями. ## Доставка и повторные попытки SDK отправляет события в `POST /v1/sdk/metrics`. Первое событие запускает отправку через секунду один раз за запуск сессии. Последующие чтения отправляются по интервалу flush (по умолчанию 60 секунд). Обычный flush выгружает накопленную очередь пачками до 50 событий. Новые события, появившиеся во время отправки, могут ждать следующего flush. При ошибке пачка возвращается в очередь с прежними ID, временем и пользовательским контекстом. Каждое новое событие получает UUID `eventId`. Backend с миграцией `004_metrics_delivery.sql` не увеличивает счётчик при повторной доставке этого ID в том же проекте и окружении. Старые SDK без ID принимаются, но повторы нельзя надёжно определить. Исторические дубликаты автоматически не исправляются. Обновляйте backend первым, затем SDK приложений. В браузере при скрытии страницы и `pagehide` делается одна небольшая попытка отправки с `keepalive`. `stop()` также инициирует отправку. В Node/SSR обязательно дождитесь `flushMetrics()` перед завершением запроса или процесса: ```ts await client.start(); try { const checkout = client.getVariant("checkout", false); await client.flushMetrics(); return checkout.value; } finally { client.stop(); } ``` Next.js `getServerFlags()` получает конфигурацию без метрик. Если нужно учитывать чтение на сервере, используйте отдельный `createServerClient()` на запрос и последовательность из примера. Не считайте одну экспозицию одновременно на сервере и в браузере, если для ваших метрик это будет повтором. Swift инициирует отправку при `willResignActive` и `stop()`. В Android вызывайте `flushMetrics()` при переходе приложения в фон. `close()` делает финальную попытку отправить до 50 событий без блокировки UI. Нативный flush асинхронный: возврат из метода не означает подтверждения доставки. ## Ограничения достоверности Очередь хранится только в памяти и вмещает 10 000 событий. При переполнении удаляются старейшие; событие больше 12 288 байт UTF-8 отбрасывается. `getStatus().droppedMetrics` показывает локальные потери по этим ограничениям. Принудительное завершение процесса, закрытие страницы, недоступность сети, блокировщики и `disableMetrics: true` также снижают полноту статистики. Дедупликация решает повторную доставку принятых событий, но не гарантирует доставку каждого события. Для биллинга по MAU и договорного аудита требуется отдельный учёт с более строгими гарантиями. Не передавайте секреты или лишние персональные данные в атрибутах контекста. ## Удаление и повторное создание проекта Новые события связаны с неизменяемым ID проекта. Новый проект с прежним ключом не получает историю удалённого проекта. Миграция `005_metrics_project_identity.sql` привязывает старые события только к проектам, уже существовавшим в момент события. Исторические события с неоднозначной принадлежностью автоматически восстановить нельзя; данные до миграции не являются доказательством точного MAU для биллинга. --- Source: https://docs.flipflag.ru/on-premise-kubernetes # Установка FlipFlag в Kubernetes Этот вариант рассчитан на ИТ-команду заказчика: Kubernetes **1.26+**, Helm 3, корпоративный PostgreSQL, ingress controller и сертификаты уже подготовлены. Chart находится в `helm/flipflag` внутри [полного self-host комплекта](https://docs.flipflag.ru/on-premise.mdx). Он устанавливает API и UI; кластер PostgreSQL не устанавливается. ## 1. Подготовьте образы и PostgreSQL Доставьте API/UI образы из `images/flipflag-images.tar` во внутренний registry. Например, для AMD64 на машине с Docker: ```bash docker load -i images/flipflag-images.tar docker tag flipflag/api:0.3.0-onprem-amd64 registry.example.com/flipflag/api:0.3.0-onprem-amd64 docker tag flipflag/web:0.3.0-onprem-amd64 registry.example.com/flipflag/web:0.3.0-onprem-amd64 docker push registry.example.com/flipflag/api:0.3.0-onprem-amd64 docker push registry.example.com/flipflag/web:0.3.0-onprem-amd64 ``` Для ARM64 исходные теги — `0.3.0-onprem`; не запускайте образ другой архитектуры. Для смешанного кластера подготовьте multi-platform image index либо node placement. Не используйте облачный образ API для коммерческой on-prem установки. DBA создаёт две отдельные базы, control и tenant, и LOGIN-роль без SUPERUSER/CREATEDB/CREATEROLE с правами на миграции. Установите `uuid-ossp` в обеих базах. DSN должны использовать `sslmode=verify-full`, фиксированный адрес tenant без `%s`, percent-encoded пароль и при необходимости частный CA. ## 2. Создайте Secrets Файлы в `/secure/` подготовьте средствами корпоративного менеджера секретов: каждый содержит только соответствующее значение. JWT-секрет должен быть случайным и одинаковым для всех реплик API. Не коммитьте файлы, значения или полученный Secret YAML. ```bash kubectl create namespace flipflag kubectl -n flipflag create secret generic flipflag-secrets \ --from-file=CONTROL_PLANE_DSN=/secure/control-dsn \ --from-file=TENANT_DSN_TEMPLATE=/secure/tenant-dsn \ --from-file=JWT_SECRET=/secure/jwt-secret ``` Если PostgreSQL использует частный CA: ```bash kubectl -n flipflag create secret generic flipflag-postgres-ca \ --from-file=ca.crt=/secure/postgres-ca.crt ``` Тогда добавьте `sslrootcert=/etc/flipflag-ca/ca.crt` в обе DSN и укажите `caSecret` в values. Для приватного registry создайте корпоративный imagePullSecret и укажите его имя в `imagePullSecrets`. ## 3. Подготовьте лицензию Один раз создайте ID установки и сохраните его в конфигурации: ```bash openssl rand -hex 16 ``` Все реплики используют **один и тот же ID**. Для офлайн-режима передайте его поставщику и получите подписанный файл: ```bash kubectl -n flipflag create secret generic flipflag-license \ --from-file=license.json=/secure/company.license ``` Для онлайн-режима вместо файла создайте Secret с ключом активации: ```bash kubectl -n flipflag create secret generic flipflag-license \ --from-file=activation-key=/secure/activation.key ``` Это альтернативные варианты. В values задаётся соответственно `offline` или `online`. Онлайн-режиму нужен исходящий HTTPS к `https://flipflag.ru/selfhost/licensing`. Новый pod получает допуск при старте: если сервер лицензий недоступен и у pod нет сохранённого допуска, его бизнес API отвечает `402`. Readiness сама по себе этого не обнаруживает. Для полностью изолированной инфраструктуры выбирайте офлайн-файл. ## 4. Установите chart Пример `/secure/flipflag-values.yaml` для AMD64 и офлайн-лицензии: ```yaml existingSecret: flipflag-secrets publicOrigin: https://flags.example.com licensing: instanceId: REPLACE_WITH_THE_ID_GENERATED_ABOVE mode: offline existingSecret: flipflag-license # Укажите только при наличии частного CA: # caSecret: flipflag-postgres-ca # imagePullSecrets: # - name: corporate-registry api: image: repository: registry.example.com/flipflag/api tag: 0.3.0-onprem-amd64 replicas: 2 web: image: repository: registry.example.com/flipflag/web tag: 0.3.0-onprem-amd64 replicas: 2 ingress: enabled: true className: nginx host: flags.example.com tls: - secretName: flipflag-tls hosts: [flags.example.com] ``` Подготовьте TLS Secret `flipflag-tls` и DNS; используйте свой ingress class. Для онлайн-режима замените `licensing.mode` на `online` и создайте соответствующий Secret из предыдущего шага. Также **обязательно** задайте постоянный volume для кеша подписанного допуска: ```yaml licensing: mode: online persistence: existingClaim: flipflag-license-state ``` PVC создаёт администратор кластера. Для двух и более реплик требуется RWX-хранилище с поддержкой POSIX file locks; UID/GID 10001 должны иметь право записи. Для одной реплики допустим RWO, но rolling update и перенос между узлами требуют отдельной проверки подключения volume. Chart отклонит online-конфигурацию без PVC. Включите volume в backup; удаление PVC удаляет кеш и заставляет снова обратиться к issuer. При недоступном issuer новый Pod использует сохранённый действующий lease до его истечения; бессрочной работы без продления нет. Настройте CPU/RAM, affinity, nodeSelector и tolerations по требованиям кластера. Две реплики сами по себе не обеспечивают распределение по разным узлам. ```bash helm lint helm/flipflag --values /secure/flipflag-values.yaml helm upgrade --install corp helm/flipflag -n flipflag \ --values /secure/flipflag-values.yaml --wait --timeout 10m kubectl -n flipflag get pods ``` Pre-install/pre-upgrade Job выполняет миграции. Ошибка миграции останавливает установку; API pods самостоятельно схему не меняют. Для несовместимой миграции старой схемы заранее остановите трафик и старые API pods. ## 5. Создайте администратора и проверьте API Однократное создание администратора; пароль из файла передаётся через stdin: ```bash API_POD=$(kubectl -n flipflag get pods \ -l app.kubernetes.io/instance=corp,app.kubernetes.io/component=api \ -o jsonpath='{.items[0].metadata.name}') kubectl -n flipflag exec -i "$API_POD" -- env \ BOOTSTRAP_EMAIL=admin@example.com BOOTSTRAP_ORG_NAME='Example Corp' \ BOOTSTRAP_NAME=Administrator ./flipflag-api bootstrap < /secure/admin-password curl -fsS https://flags.example.com/v1/license/status ``` Войдите в UI, создайте тестовый проект/флаг и проверьте SDK evaluate через ingress. Health checks не заменяют проверку tenant БД и лицензии. Одна реплика API может занимать до 10 control + 2 tenant соединений; учитывайте миграции и операции DBA. ## Продление, ротация и эксплуатация Офлайн-файл заменяется в Secret с тем же именем и ID: ```bash kubectl -n flipflag create secret generic flipflag-license \ --from-file=license.json=/secure/renewed.license --dry-run=client -o yaml \ | kubectl apply -f - ``` Файл смонтирован целиком и перечитывается приложением после обновления volume Kubernetes; доставка изменения не мгновенна. Проверьте `/v1/license/status` у каждой реплики. Для онлайн-режима обычная оплата не требует нового ключа; при его замене обновите Secret `activation-key` и выполните контролируемый rollout API. После ротации DSN/JWT также требуется rollout; смена JWT завершает старые сессии. Используйте корпоративный backup/PITR PostgreSQL. Сохраняйте обе базы, Secrets и ID установки согласованно; Helm rollback не откатывает схему БД. Настройте мониторинг, проверку восстановления и NetworkPolicy: ingress → web:8080, web → api:8080, API/migration → PostgreSQL, DNS и необходимый egress для онлайн-лицензии. SDK в закрытой сети доставляются через внутренние npm/Maven/Swift репозитории. Окончание лицензии и безопасные defaults приложения описаны в [руководстве Compose](https://docs.flipflag.ru/on-premise.mdx#продление-и-окончание-подписки). --- Source: https://docs.flipflag.ru/on-premise # FlipFlag на сервере вашей компании FlipFlag self-host размещает интерфейс, API и PostgreSQL в инфраструктуре заказчика. Одна установка обслуживает одну организацию с проектами, окружениями и пользователями. SDK обращаются к адресу вашей установки. Для Kubernetes используйте [отдельную инструкцию](https://docs.flipflag.ru/on-premise-kubernetes.mdx). ## Что получает заказчик Полный комплект **0.3.0** для Linux AMD64 или ARM64 содержит установщик, Compose, Helm chart и готовые образы API, интерфейса, PostgreSQL и HTTPS proxy. Go, Node.js, исходники приложения и доступ к Docker registry для установки комплекта не нужны. Лицензия выдаётся поставщиком отдельно после подтверждения оплаты по договору. ```text Браузер администратора ─┐ ├─ HTTPS → ваш FlipFlag → API → PostgreSQL SDK вашего приложения ─┘ │ └─ исходящий HTTPS → лицензирование FlipFlag только в онлайн-режиме ``` Бизнес-данные остаются у заказчика. Онлайн-проверка передаёт ключ активации и ID установки; содержимое БД, флаги и пользователи в этот запрос не входят. В изолированной сети используйте подписанный файл лицензии: обращения к поставщику не нужны. ## 1. Подготовьте сервер | Требование | Что проверить | |---|---| | Платформа | Linux, архитектура Docker-сервера AMD64 или ARM64 | | Docker | Работающий Docker Engine и доступ текущего пользователя к Docker | | Compose | Plugin версии **2.24.4 или новее** | | Утилиты | Bash, curl, OpenSSL; доступный интерактивный терминал | | Ресурсы для первого пилота | Начните с 2 vCPU, 4 ГБ RAM и SSD; ёмкость проверяется вашей нагрузкой | | Онлайн-установка | Исходящий HTTPS к `flipflag.ru` для загрузки и лицензирования | | Доступ пользователей | Свободный выбранный веб-порт; для автоматического HTTPS — DNS и TCP 80/443 | Проверка: ```bash docker info docker compose version bash --version curl --version openssl version ``` Установщик проверяет зависимости, но **не устанавливает Docker**, не меняет DNS и firewall. Docker API даёт доступ к секретам контейнеров: предоставляйте его только администраторам. ## 2. Запустите одну команду Из каталога, в котором хотите хранить установку: ```bash curl -fsSL https://flipflag.ru/selfhost/downloads/install.sh | bash ``` Загрузчик определит архитектуру Docker-сервера, скачает архив по HTTPS, проверит SHA-256 и запустит мастер. Файлы появятся в `./flipflag-selfhost`. Для другого каталога: ```bash curl -fsSL https://flipflag.ru/selfhost/downloads/install.sh \ | FLIPFLAG_INSTALL_DIR=/opt/flipflag bash ``` Текущий пользователь должен иметь право записи в выбранный каталог. Для предварительного просмотра загрузчика сохраните его отдельно: ```bash curl -fsSLo /tmp/flipflag-download.sh https://flipflag.ru/selfhost/downloads/install.sh less /tmp/flipflag-download.sh bash /tmp/flipflag-download.sh ``` SHA-256 проверяет целостность архива; доверие к загрузчику и checksum обеспечивается HTTPS. ## 3. Ответьте на вопросы мастера Пример параметров — вводите их по приглашениям мастера: | Поле | Пример | |---|---| | Компания | `Example Corp` | | Веб-порт | `8088` | | Домен | Оставьте пустым для IP или введите `flags.example.com` | | Режим доступа | IP / автоматический HTTPS / корпоративный proxy | | Email администратора | `admin@example.com` | | Имя администратора | `Administrator` | | Пароль | Свой пароль, 12–72 байта; ввод скрыт и повторяется | | Лицензия | Онлайн-ключ или путь к подписанному файлу | Мастер создаст пароли БД и JWT-секрет, загрузит готовые образы, запустит сервисы, активирует лицензию и создаст первого администратора. Он дождётся health checks и проверит вход. Адрес входа появится в конце установки. Пароль администратора не сохраняется в настройках мастера и не передаётся аргументом процесса. ### Вариант A: IP и порт Например: `http://192.0.2.10:8088`. Мастер предложит IP сервера и позволит исправить его. Веб-порт публикуется на интерфейсах сервера; сетевой доступ разрешается вашим firewall. HTTP подходит для доверенной тестовой сети. Для доступа через интернет подготовьте HTTPS. ### Вариант B: домен и автоматический HTTPS Заранее направьте DNS A/AAAA домена на сервер. TCP 80/443 должны быть свободны и доступны снаружи; ошибочная AAAA-запись также может помешать выдаче сертификата. Выберите автоматический HTTPS. Caddy получит сертификат и будет обновлять его. Пользователи откроют `https://flags.example.com`, внутренний веб-порт останется на loopback. Публичный ACME требует сетевой доступ к центру сертификации и доступ центра к серверу. ### Вариант C: корпоративный reverse proxy Выберите соответствующий режим. Установка покажет upstream, например `http://127.0.0.1:8088`. Направьте **весь** внешний сайт на него, включая `/v1/` и `/config.js`. Пример для nginx на том же хосте, после получения корпоративного сертификата: ```nginx server { listen 443 ssl; server_name flags.example.com; ssl_certificate /etc/nginx/tls/fullchain.pem; ssl_certificate_key /etc/nginx/tls/privkey.pem; location / { proxy_pass http://127.0.0.1:8088; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` Если proxy в другом контейнере/на другом узле, его `127.0.0.1` не является адресом хоста FlipFlag. Подготовьте маршрут через общую сеть или приватный адрес; измените `BIND_ADDRESS` и ограничьте доступ сетевыми правилами. Внешний домен заработает после настройки proxy. API и PostgreSQL отдельно наружу не публикуются. ## 4. Активируйте лицензию ### Онлайн Вставьте полученный от поставщика ключ в скрытое поле мастера. При первой активации он привязывается к ID установки. Сервер получает подписанный допуск, проверяет его локально и запрашивает обновление при запуске и затем раз в час. Допуск действует **не более 72 часов с выдачи и никогда не дольше оплаченного срока**. 72 часа — предел ранее выданного допуска при потере связи, а не дополнительные дни подписки. При обычном продлении поставщик подтверждает оплату; менять ключ не требуется. ### Закрытая сеть и офлайн-файл На машине с интернетом скачайте комплект и checksum. Пример для AMD64: ```bash curl -fSLO https://flipflag.ru/selfhost/downloads/flipflag-selfhost-0.3.0-linux-amd64.tar.gz curl -fSLO https://flipflag.ru/selfhost/downloads/flipflag-selfhost-0.3.0-linux-amd64.tar.gz.sha256 sha256sum -c flipflag-selfhost-0.3.0-linux-amd64.tar.gz.sha256 ``` Для ARM64 замените `amd64` на `arm64` в обоих именах. Перенесите оба файла в закрытую сеть, повторите проверку, затем: ```bash tar -xzf flipflag-selfhost-0.3.0-linux-amd64.tar.gz cd flipflag-selfhost-0.3.0-linux-amd64 ./install.sh ``` Выберите активацию файлом. Мастер покажет ID установки: передайте его поставщику, получите подписанный файл и укажите путь к нему. Интернет и доступ к registry не требуются. Файл действует до оплаченной даты; для следующего периода получите новый файл для **того же ID**. Для HTTPS в закрытой сети используйте корпоративный proxy и сертификат. ## 5. Проверьте работу и подключите приложение Все дальнейшие команды выполняются из каталога установки: ```bash cd flipflag-selfhost docker compose ps docker compose exec -T api ./flipflag-api license-status curl -fsS http://127.0.0.1:8088/healthz curl -fsS http://127.0.0.1:8088/v1/license/status ``` Подставьте свой порт и адрес. Войдите под созданным администратором, создайте проект, окружение и тестовый флаг, выпустите SDK-ключ. **SDK-ключ проекта и ключ активации on-prem — разные секреты.** Ключ активации не помещают в браузер или мобильное приложение. ```ts import { createClient } from "@flipfeatureflag/js"; const flags = createClient({ url: "https://flags.example.com", // без добавления /v1 sdkKey: "PROJECT_SDK_KEY", env: "prod", context: { userId: "user-123" }, }); await flags.start(); const newCheckout = flags.isEnabled("new_checkout", false); // false должен вести к рабочему старому checkout, а не к пустому экрану. ``` Для браузерного SDK укажите origin приложения в `CORS_ALLOW_ORIGINS` API, например `https://shop.example.com`. Сам интерфейс установки также должен оставаться в разрешённом списке. В базовом Compose значение берётся из `PUBLIC_ORIGIN`; для нескольких origins добавьте отдельный Compose override с точным списком через запятую. Пример отдельного `compose.cors.yaml`: ```yaml services: api: environment: CORS_ALLOW_ORIGINS: https://flags.example.com,https://shop.example.com ``` Добавьте `compose.cors.yaml` в конец существующего `COMPOSE_FILE` в `.env`, сохранив уже выбранные файлы HTTPS/proxy/внешней БД. Если списка нет, используйте `COMPOSE_FILE=compose.yaml:compose.cors.yaml`. Затем примените конфигурацию: ```bash docker compose up -d --no-build --pull never --force-recreate api ``` Серверным SDK браузерный CORS не нужен. Не храните секретные значения во флагах, которые доступны браузерным/мобильным SDK-ключам. ## Продление и окончание подписки Проверить состояние можно без действующей лицензии. Новый файл/ключ передаётся через stdin: ```bash docker compose exec -T api ./flipflag-api license-install < /secure/renewed.license # Для замены онлайн-ключа или немедленной повторной активации после оплаты: docker compose exec -T api ./flipflag-api license-activate < /secure/activation.key ``` Импорт офлайн-файла в Compose отключает сохранённую онлайн-активацию. По окончании допуска бизнес API, включая login и SDK evaluate/metrics, отвечает **HTTP 402 Payment Required**. Контейнеры и БД продолжают работать; данные не удаляются. Команды обновления лицензии, health endpoints и `/v1/license/status` доступны. SDK сохраняют последний успешный снимок в памяти и используют defaults при его отсутствии. Новые процессы/страницы не наследуют этот кэш. Отсутствие ответа не должно блокировать работу приложения: предусмотрите defaults и обработку ошибок; подробнее в [разделе об ошибках SDK](https://docs.flipflag.ru/error-handling.mdx). Отзыв онлайн-доступа приходит при следующей успешной проверке. В изолированной сети ранее выданный файл нельзя отозвать удалённо до его окончания. ## Корпоративный PostgreSQL Подготовьте две отдельные базы — control и tenant — и LOGIN-роль без SUPERUSER/CREATEDB/CREATEROLE. Роль должна владеть базами/объектами миграций. Расширение `uuid-ossp` заранее устанавливает DBA, если приложение не вправе его создать. Мастер с встроенной БД — самый простой путь; внешний PostgreSQL подключается отдельно: 1. Загрузите образы: `docker load -i images/flipflag-images.tar`. Для AMD64 скопируйте `compose.amd64.env.example` в `.env` перед `./scripts/init.sh`; для ARM64 используется `.env.example`. Выполните `./scripts/init.sh` и задайте `.env`: `PUBLIC_ORIGIN`, порт, стабильный ID и параметры лицензирования. 2. Замените `secrets/control_dsn` и `secrets/tenant_dsn` настоящими URI с `sslmode=verify-full`. Tenant URI фиксированный, без `%s`. Пароли percent-encode. 3. Сохраните mode `0444` файлов внутри закрытого каталога `secrets/` (`0700`). 4. Добавьте в `.env` `COMPOSE_FILE=compose.yaml:compose.external.yaml`. 5. Запустите `docker compose up -d --no-build --pull never --wait`, активируйте лицензию и однократно создайте администратора. ```bash BOOTSTRAP_EMAIL=admin@example.com BOOTSTRAP_ORG_NAME='Example Corp' \ BOOTSTRAP_NAME=Administrator ./scripts/bootstrap.sh < /secure/admin-password ``` Для частного CA смонтируйте сертификат read-only в API и dbtools через override; укажите один и тот же `sslrootcert` в обеих DSN. Смена DSN требует пересоздания API. Не запускайте мастер встроенной БД поверх вручную настроенной внешней установки. ## Резервные копии, перезапуск и обновления ```bash ./scripts/backup.sh # Пример пути: backups/20261010T120000Z ``` Backup на короткое время останавливает API/UI, создаёт два согласованных дампа и запускает сервисы обратно. Копируйте дампы в зашифрованное внешнее хранилище. Отдельно сохраняйте `.env`, `secrets/`, `installation/`, данные лицензии из volume и, если нужно, сертификаты Caddy. Дампы БД не содержат весь этот набор. Сохраняйте ID установки при переносе и заранее проверяйте восстановление. :::danger Восстановление заменяет данные Команда ниже перезаписывает обе базы данными из backup. Сначала проверьте восстановление на отдельной установке и сохраните текущие данные. При ошибке приложение остаётся остановленным. ::: ```bash ./scripts/restore.sh backups/20261010T120000Z ``` Для обычного перезапуска без удаления данных: ```bash docker compose restart ``` Не используйте `docker compose down -v`: ключ `-v` удаляет постоянные volumes. Для обновления получите новый полный комплект от поставщика, сделайте backup, загрузите новые образы, обновите Compose/настройки по инструкции выпуска и выполните `docker compose up -d --wait`. Повтор загрузчика версии 0.3.0 — продолжение установки, а не автоматическое обновление на будущий релиз. Миграции могут быть несовместимы со старым бинарником: откат требует прежних образов и обоих согласованных дампов. ## Если установка прервалась Повторите ту же команду загрузчика из того же родительского каталога либо `./install.sh` из уже распакованного комплекта. Мастер сохранит существующие настройки и секреты, не заменит созданного администратора. Не удаляйте `.env`, `secrets/` или `installation/`. | Симптом | Что проверить | |---|---| | Docker/Compose не найден | Установите зависимости; Compose должен быть 2.24.4+ | | Порт занят | Освободите его либо исправьте `HTTP_PORT` и порт в `PUBLIC_ORIGIN` перед повтором | | Сертификат не выдан | DNS A/AAAA, доступность и занятость 80/443, исходящий ACME | | Неверный ключ / отказ активации | Оплату, выбранный ключ и привязку к ID; проверьте исходящий HTTPS | | `HTTP 402` | `license-status`, оплаченную дату, часы сервера и получение продления | | Контейнер `healthy`, но API заблокирован | Health check проверяет инфраструктуру, а не право на бизнес API | | Браузерный SDK получает CORS-ошибку | Разрешённый origin приложения и проксирование `/v1/` | | Не удаётся войти после восстановления | Согласованность обеих БД, JWT-секрета и настроек установки | ```bash docker compose ps docker compose logs --tail=100 api web ``` Перед передачей логов удаляйте токены, SDK-ключи, DSN и пользовательские данные. Один сервер не обеспечивает HA. SSO/SCIM и автоматическая retention метрик не входят в текущую поставку; требования корпоративного внедрения согласуются отдельно. --- Source: https://docs.flipflag.ru/sdk/android # Android SDK Исходники находятся в `packages/android` репозитория SDK; [ветка аудита](https://github.com/Mthu042/flipflag-sdk/tree/sdk-hardening-20261011) содержит исправления. Наличие Maven publication в Gradle не означает публикацию в Maven Central. Репозиторий приватный: запросите у поставщика доступ, исходники или готовый AAR. Команды сборки ниже предполагают, что исходники уже получены. До отдельного публичного выпуска соберите AAR или опубликуйте библиотеку в корпоративном Maven repository. ## Сборка и подключение Нужны JDK 21 и Android SDK 34. В каталоге `packages/android`: ```bash ./gradlew test assembleRelease lint ``` Готовый AAR: `build/outputs/aar/flipfeatureflag-sdk-release.aar`. Для локального подключения скопируйте его в `app/libs/`: ```kotlin dependencies { implementation(files("libs/flipfeatureflag-sdk-release.aar")) implementation("com.squareup.okhttp3:okhttp:4.12.0") } ``` У локального AAR нет автоматически доставляемого POM с транзитивными зависимостями, поэтому OkHttp здесь указан явно. В опубликованной Maven-библиотеке зависимости поставляются через её POM. Min SDK — 21; разрешение INTERNET включено в manifest библиотеки. ## Использование ```kotlin import com.flipfeatureflag.sdk.* val flags = FlipFeatureFlagClient(FlipFeatureFlagConfig( url = "https://flags.example.com", sdkKey = "PROJECT_SDK_KEY", context = SdkContext(userId = "user-123") )) flags.start() // Не блокирует UI-поток. val newCheckout = flags.isEnabled("new_checkout", defaultValue = false) ``` При первом запросе используется default, при временном сбое — последний успешный снимок. `getStatus()` показывает `ready`, `httpStatus` и описание ошибки. Изменение контекста сразу сбрасывает прошлые результаты и запускает обновление: ```kotlin flags.updateContext(SdkContext("user-456", mapOf("plan" to "pro"))) flags.stop() // Пауза, например в background. flags.start() // Возобновление. flags.close() // Окончательно освободить потоки и соединения. ``` Жизненным циклом SDK управляет приложение. Используйте HTTPS с доверенным CA; не отключайте проверку TLS и не разрешайте cleartext глобально. В закрытой сети доставьте AAR и зависимости через корпоративное хранилище. [Ошибки и окончание on-prem лицензии](../error-handling.mdx). --- Source: https://docs.flipflag.ru/sdk/ios # iOS SDK Нативная реализация находится в `packages/ios` репозитория SDK. Исправления аудита доступны в [ветке sdk-hardening-20261011](https://github.com/Mthu042/flipflag-sdk/tree/sdk-hardening-20261011). Корневой `Package.swift` этой ветки позволяет подключить библиотеку через SwiftPM; репозиторий приватный — поставщик должен сначала предоставить доступ или передать исходники для вашего Git-зеркала. Без этого доступа GitHub вернёт 404. Минимальная версия iOS — 13. Для коммерческой поставки закрепите проверенный commit или выпущенный tag вместо плавающей ветки. В закрытой сети зеркалируйте пакет. ```swift .package(url: "https://github.com/Mthu042/flipflag-sdk.git", branch: "sdk-hardening-20261011") ``` Добавьте product `FlipFeatureFlag` в зависимости target приложения: ```swift import FlipFeatureFlag let flags = FlipFeatureFlagClient(config: FlipFeatureFlagConfig( url: "https://flags.example.com", sdkKey: "PROJECT_SDK_KEY", context: SdkContext(userId: "user-123") )) flags.start() // Запрос выполняется асинхронно. let newCheckout = flags.isEnabled("new_checkout", defaultValue: false) ``` Пока ответ не получен, используется default; при ошибке сохраняется последний успешный снимок текущего контекста. `getStatus()` показывает `ready` и `error?.httpStatus`, в том числе 402. Не блокируйте главный поток ожиданием сети. При изменении пользователя/атрибутов передайте полный контекст: ```swift flags.updateContext(SdkContext(userId: "user-456", attributes: ["plan": .string("pro")])) flags.stop() // При уходе в background/завершении нужного жизненного цикла. // flags.start() — возобновить работу. ``` Используйте HTTPS с доверенным сертификатом. Не отключайте ATS глобально ради внутреннего HTTP-сервера. При внедрении `URLSession` приложение отвечает за её настройки TLS и redirect policy. Метрики best effort; приватные данные в attributes не помещайте. Проверки исходников: `swift test` из корня SDK либо из `packages/ios`. Общий контракт ошибок описан [отдельно](../error-handling.mdx). --- Source: https://docs.flipflag.ru/sdk/javascript # JavaScript (Browser) ## Install ```bash npm install @flipfeatureflag/js ``` ## Usage ```ts import { createClient } from "@flipfeatureflag/js"; const client = createClient({ url: "https://api.example.com", sdkKey: "YOUR_SDK_KEY", env: "prod", context: { userId: "user-123", attributes: { plan: "pro" } }, }); await client.start(); const enabled = client.isEnabled("new_checkout"); const variant = client.getVariant("new_checkout"); ``` --- Source: https://docs.flipflag.ru/sdk/next # Next.js ## Install ```bash npm install @flipfeatureflag/next @flipfeatureflag/react @flipfeatureflag/js @flipfeatureflag/node ``` ## Client Provider ```tsx "use client"; import { FlipFlagProvider } from "@flipfeatureflag/next/client"; export default function App({ Component, pageProps }) { return ( ); } ``` ## Server Helpers ```ts import { getServerFlags } from "@flipfeatureflag/next/server"; export async function getServerSideProps() { const flags = await getServerFlags({ url: "https://api.example.com", sdkKey: "YOUR_SDK_KEY", context: { userId: "user-123" }, }); return { props: { flags } }; } ``` ## Версия и изоляция контекста Раздельные `/client` и `/server` exports относятся к [исправленному исходному SDK](https://github.com/Mthu042/flipflag-sdk/tree/sdk-hardening-20261011). До публикации соответствующего npm-релиза соберите эту ветку; наличие документации не означает, что новый export уже появился в ранее установленном пакете. `getServerFlags` выполняет одну попытку без фоновых таймеров/метрик. При ошибке возвращается пустой набор — выбирайте рабочие defaults. Не переиспользуйте одну мутируемую инстанцию между параллельными запросами разных пользователей. Статистика чтения на сервере подключается отдельно через `createServerClient`. На каждый запрос создавайте свой клиент, после `start()` читайте флаг через `getVariant()` и дожидайтесь `flushMetrics()` перед `stop()`. Подробные правила подсчёта и ограничения доставки: [Статистика](../metrics.mdx). --- Source: https://docs.flipflag.ru/sdk/node # Node.js ## Install ```bash npm install @flipfeatureflag/node ``` ## Usage ```ts import { createClient } from "@flipfeatureflag/node"; const client = createClient({ url: "https://api.example.com", sdkKey: "YOUR_SDK_KEY", env: "prod", context: { userId: "user-123" }, }); await client.start(); const enabled = client.isEnabled("new_checkout"); ``` --- Source: https://docs.flipflag.ru/sdk/react-native # React Native ## Install ```bash npm install @flipfeatureflag/react-native @flipfeatureflag/js ``` ## Provider ```tsx import { FlipFlagProvider } from "@flipfeatureflag/react-native"; export default function App() { return ( ); } ``` ## Hooks ```tsx import { useFlag, useVariant, useFlagsStatus, useUpdateContext } from "@flipfeatureflag/react-native"; function Screen() { const { enabled, value } = useFlag("new_checkout"); const variant = useVariant("new_checkout"); const status = useFlagsStatus(); const updateContext = useUpdateContext(); return null; } ``` --- Source: https://docs.flipflag.ru/sdk/react # React ## Install ```bash npm install @flipfeatureflag/react @flipfeatureflag/js ``` ## Provider ```tsx import { FlipFlagProvider } from "@flipfeatureflag/react"; function App() { return ( ); } ``` ## Hooks ```tsx import { useFlag, useVariant, useFlagsStatus, useUpdateContext } from "@flipfeatureflag/react"; function Checkout() { const { enabled, value } = useFlag("new_checkout"); const variant = useVariant("new_checkout"); const status = useFlagsStatus(); const updateContext = useUpdateContext(); return value === true ? : ; } ``` ## Updating context after login ```tsx import { useUpdateContext } from "@flipfeatureflag/react"; function AuthListener({ userId }) { const updateContext = useUpdateContext(); useEffect(() => { if (userId) { updateContext({ userId }); } }, [userId, updateContext]); return null; } ``` ## useFlag return value `useFlag` returns `{ value, enabled }`: - `value` is the current flag value (boolean/string/number/object). - `enabled` is `true` when the flag exists in the backend response and `reason !== "disabled"`. - If the flag is missing from the response, `enabled` is `false`. - If `reason` is `default`, `enabled` is still `true` as long as the flag was returned. --- Source: https://docs.flipflag.ru/sdk/vue # Vue ## Install ```bash npm install @flipfeatureflag/vue @flipfeatureflag/js ``` ## Plugin ```ts import { createApp } from "vue"; import { createFlipFlag } from "@flipfeatureflag/vue"; const app = createApp(App); app.use( createFlipFlag({ config: { url: "https://api.example.com", sdkKey: "YOUR_SDK_KEY", env: "prod", }, }), ); ``` ## Composables ```ts import { useFlag, useVariant, useFlagsStatus, useUpdateContext } from "@flipfeatureflag/vue"; export default { setup() { const { enabled, value } = useFlag("new_checkout"); const variant = useVariant("new_checkout"); const status = useFlagsStatus(); const updateContext = useUpdateContext(); return { enabled, value, variant, status }; }, }; ``` ## Updating context after login (Vue) ```ts import { useUpdateContext } from "@flipfeatureflag/vue"; export default { setup() { const updateContext = useUpdateContext(); function onLogin(userId) { updateContext({ userId }); } return { onLogin }; }, }; ``` ## Reason semantics `reason` is interpreted as: - `rule_match` — a targeting rule matched. - `fallthrough` — flag enabled, no rules matched (or no rules). - `default` — backend returned the default path for an existing flag. - `disabled` — flag disabled on backend. --- Source: https://docs.flipflag.ru/types # Types ## SdkContext ```ts { userId: string; attributes?: Record; } ``` ## SdkFlagEvaluation ```ts { value: boolean | string | number | Record; variationKey: string; reason: "rule_match" | "fallthrough" | "default" | "disabled"; } ``` ## SdkEvaluateResponse ```ts { flags: Record; evalId?: string; updatedAt?: string; } ``` ## SdkMetricEvent ```ts { flagKey: string; variationKey: string; reason: string; ts: string; // ISO date context?: SdkContext; } ```