Provisa¶
Подключите свои базы данных. Запрашивайте их через 5 минут на GraphQL, gRPC, SQL или MCP, поверх любого API или протокола.
Provisa ставит один API над всеми вашими данными. Направьте его на свои базы данных и бизнес-приложения, опишите, как они связаны, и запрашивайте объединённый результат через REST, GraphQL, SQL, gRPC, MCP, JSON:API, Arrow Flight, pgwire или Bolt.
Это работает, потому что всё берётся из одной модели: ваших доменов, связей между таблицами и политик для них по всем источникам. Provisa работает по этой модели и управляет доступом по ней же, так что синхронизировать нечего. Зарегистрированные связи — единственные соединения, которые может сделать запрос, а политики доступа компилируются в каждый план запроса. Из одной модели следуют четыре вещи:
- Федерация. 73 коннектора достают до более чем 85 видов источников, среди них Salesforce, ServiceNow и Stripe. SaaS-системы, на которых работает ваш бизнес, читаются как таблицы рядом с вашими базами данных, на своём месте, без предварительного конвейера в хранилище. Запрашивайте их на SQL, GraphQL или Cypher по девяти протоколам.
- Метрики. Метрика — это именованный, управляемый агрегат. Вы определяете её один раз, и любой инструмент и язык, который её запрашивает, получает одно и то же определение.
- Онтология. Бизнес-глоссарий — это граф понятий, их определений и связей между ними. Provisa сопоставляет его с таблицами и столбцами, где лежат значения, и поэтому может отвечать на вопросы о ваших данных. Понятие остаётся черновиком, пока не дойдёт до данных напрямую или через другие понятия. Глоссарий говорит, что такое понятие; метрика говорит, как вычисляется число.
- Управление доступом. Шесть уровней проверок компилируются в каждый план запроса, на любом языке и по любому протоколу, и каждый запрос записывается одинаково: кто что запросил, от имени какой роли, по какой политике. Трассировки, метрики и журналы зарегистрированы как таблицы, доступные для запросов, рядом с бизнес-данными.
Спрашивать можно на GraphQL, Cypher или SQL, подключаться — через pgwire, Bolt, gRPC, REST, Arrow Flight или JDBC. Каждый язык запросов приводится к одному промежуточному представлению, и управление доступом применяется там, один раз, так что политика не может разойтись между языками. На выходе эта форма переводится в собственный диалект каждого источника. Новый язык запросов — это новый фронтенд на том же ядре.
Через него проходят и чтение, и запись. Запрос по нескольким источникам распределяется через слой федерации. Запись и чтение из одного источника идут прямо к его драйверу, под тем же управлением и обычно с ответом быстрее 100 мс. Колоночная потоковая передача Arrow Flight встроена.
Словарь модели невелик: домены, связи, роли и политики. Поэтому её легко читать и проверять, и можно прочитать набор политик и понять, что он делает. Сам Provisa является лёгким компилятором запросов. Он никогда не стоит на пути ваших данных как среда выполнения. Он превращает запрос в нативные запросы, направляет их и отходит в сторону, поэтому всё работает быстро.
Использовать его можно двумя способами, и они сочетаются:
- Для модернизации. Смоделируйте свои данные, дайте Provisa сгенерировать нативный SQL для каждого источника, затем возьмите этот SQL и перенесите его в целевую систему. Provisa служит мостом на время перехода, и потом от него можно отказаться.
- Для постоянного управления. Оставьте его путём, по которому идёт каждый запрос, чтобы определение, применение и аудит оставались вместе, пока существуют данные.
Попробовать демонстрацию¶
Быстрее всего — живая демонстрация в браузере, без установки: provisa.dev/demos. Каждая открывает личную песочницу с обзорной экскурсией.
Из копии этого репозитория можно запустить любую демонстрацию на своей машине:
./start-ui-install.sh --list-demos # the demos you can run, and which are published
./start-ui-install.sh --demo weblogs # start one, with its tour
Опубликованная демонстрация загружается готовым пакетом; остальные запускаются из demo/named/<name>/. Все параметры описаны в docs/sales-engineer-demos.md.
Модель федерации¶
Весь замысел держится на четырёх идеях. Любой источник сводится к таблицам. Любой запрос сводится к одной форме, похожей на SQL. Достижимость решает, что запрашивается вживую, а что сначала копируется. А стратегия актуальности поддерживает каждую копию и каждый производный набор данных настолько свежими, насколько нужно.
Начнём с источников. Каждый выражается как набор двумерных таблиц поверх одной общей системы типов, и это единственный контракт, который источник должен выполнить, чтобы войти в ваши данные. Таблица MySQL или PostgreSQL уже им является. Результат запроса GraphQL становится таблицей, когда его выравнивают. Хранилища триплетов SPARQL и Neo4j совсем не похожи на таблицы, но вы задаёте запрос с табличным результатом, и этот запрос становится адаптером. Каким бы ни был источник, система видит строки, столбцы и типы. Подключить новый вид источника — значит выполнить этот единственный контракт, иногда с небольшой помощью человека. Отдельную интеграцию никто не пишет.
С запросами то же самое. SQL со всеми его диалектами — это язык анализа поверх таблиц, поэтому форма, похожая на SQL, — естественная общая цель. Так что любой запрос, на каком бы языке он ни пришёл, сначала приводится к этой форме. SQL и GraphQL приводятся легко. Пути и графовая семантика Cypher требуют настоящей работы, но и они доходят до цели. Поскольку всё проходит через одну форму раньше всего остального, управление доступом применяется в одном месте, на каком бы языке ни пришёл запрос.
С табличными источниками и одной формой запросов федерация может охватить и живые запросы, и хранилище данных: то, что делает движок живых запросов вроде Trino, плюс материализацию, на которую такие движки опираются. Связывает их достижимость. Может ли движок запросить источник там, где тот находится, или его данные сначала нужно скопировать туда, где их можно запрашивать? Ответ делит данные на то, что читается вживую, и то, что копируется.
У большинства баз данных уже есть какая-то живая связь: ATTACH в DuckDB, postgres_fdw в PostgreSQL, внешние ссылки в Databricks. Поэтому большинство баз может до какой-то степени служить движком федерации. Ни одна не охватывает всё. Каждая достаёт до определённого набора источников и копирует остальное, и ни одна не говорит прямо, что есть что. Модель делает достижимость явной — как определённый набор методов для каждого источника, которые говорят, что движок достаёт вживую и, методом исключения, что нужно копировать.
Остаётся актуальность. Насколько свежей должна быть копия каждого источника, до которого движок не достаёт? На практике ответов немного: по требованию, по расписанию, по сигналу изменения (CDC, водяной знак, снимок) или зафиксированная. Выбор одного варианта для каждого источника — это вся политика актуальности.
Производные наборы данных укладываются в ту же форму: производные таблицы, агрегаты, результат преобразования. Они пишутся в той же форме, поэтому lineage получается сам собой. Путь от каждой исходной системы до итогового результата — это определение, которое его породило, и его можно прочитать от начала до конца. Построение таких наборов переносит вопрос актуальности на шаг дальше: обновляется ли набор по расписанию, только когда выполнены его предусловия, непрерывно или как зафиксированный исторический снимок? Варианты — тот же небольшой набор, что и для копии источника, так что политика построения производного набора пользуется тем же словарём.
Отсюда прямо следуют размерные модели. Факты и измерения схемы «звезда» — такие же производные наборы, как и любые другие. Измерение — это согласованная проекция без дубликатов, таблица фактов — соединение с агрегатом, сведённое к зерну, и у каждого своя политика построения и актуальности. Медленно меняющимся измерениям ничего особенного не нужно: зафиксированный снимок — это история типа 2, перестройка по расписанию — тип 1. Поскольку схема определена в модели и не привязана к таблицам одного хранилища, те же факты и измерения можно построить в Oracle, в Databricks или оставить виртуальными поверх MPP-движка, без перемоделирования.
Data Vault укладывается так же, на слой раньше. Хабы — это наборы бизнес-ключей без дубликатов, связи (links) — зарегистрированные отношения между ними, а сателлиты — наборы атрибутов только для вставки, с отметкой времени, хранящие историю. Сателлит — это просто производный набор со стратегией сигнала изменения: дата загрузки плюс hashdiff — это захват изменений для описательных атрибутов, а история только со вставками — это стратегия зафиксированного снимка. Таблицы point-in-time и bridge — ещё несколько производных наборов, построенных ради скорости запросов. Так что raw vault — это набор производных наборов данных в модели, а схема «звезда» — проекция из него, и то и другое генерируется и переносится между движками. Методологию по-прежнему решаете вы: что станет хабом, какое зерно у сателлита, как делить. Когда решение принято, оно живёт в модели. Никакой ETL не привязывает его намертво к одному хранилищу.
Оба шаблона объявляются двумя сокращениями, а не написанными вручную представлениями. Это строительные блоки любой «звезды» и любого Data Vault, и они не привязывают вас ни к одному из методов:
entity— проекция источника с ключом и без дубликатов, которая может хранить историю. Объявите ключ, атрибуты и режим истории, и Provisa построит материализованное представление. Если попросить историю, вместо него будет построено битемпоральное MV (scd2→ delta,snapshot→ snapshot). Одна конструкция даёт вам измерение Кимбалла (SCD1 или SCD2) или хаб с сателлитом Data Vault.factсоединяется с ключами сущностей, сводится к объявленному зерну и агрегирует показатели. Provisa строит агрегатное MV плюс зарегистрированные связи с сущностями. Одна конструкция даёт вам таблицу фактов «звезды» или link Data Vault; факт без показателей — это чистый link набора ключей.
Каждая entity или fact превращается ровно в те материализованные представления, битемпоральные настройки и связи, которые модельер иначе написал бы вручную, так что хранилище остаётся в модели и переходит между движками без перемоделирования. Объявите их в интерфейсе администратора (форма Model) или через API администратора (registerEntity / registerFact). Модель сама генерирует «звезду» Кимбалла или Data Vault и не навязывает ни то, ни другое.
Путешествие во времени¶
Путешествие во времени — это хранение каждой версии строки вместо её перезаписи, чтобы можно было спросить, какими данные были в любой прошлый момент. Движки сильно различаются тем, насколько эффективно они это умеют, поэтому Provisa делает это частью определения материализованного представления, каким бы ни был механизм хранения. Объявите один раз — и это работает на любом хранилище, способном держать материализованное представление.
Переносимым это делает то, что всё происходит только добавлением. Записанная версия никогда не изменяется и не удаляется. Обычный битемпоральный приём — закрыть строку, дописав дату «действует до», — требует UPDATE, а многие движки не умеют делать его дёшево или вообще над федеративным хранилищем. Поэтому каждое обновление добавляет строки, а то, какая версия действовала в данный момент, вычисляется при чтении по журналу. Добавлять можно двумя способами:
- Snapshot добавляет весь свежий набор данных с отметкой системного времени обновления. Сравнения различий нет, и это корректно на любом движке, но хранилище растёт на полную копию при каждом обновлении.
- Delta добавляет только то, что изменилось, плюс надгробия для удалённых ключей. Дельту вычисляет сам движок, анти-соединениями внутри
INSERT … SELECT. Provisa никогда не собирает её построчно. Это компактнее, и нужен ключ сущности.
Так Provisa ведёт системное время — когда он записал версию. Время действия — когда факт верен для бизнеса — берётся из собственного SELECT представления и сохраняется. Движки, способные на большее, вроде нативных снимков Iceberg или MERGE, затрагивающего меньше строк, можно использовать за тем же объявлением; путь только с добавлением — это нижняя планка, корректная везде.
Для чтения не нужен особый синтаксис. Простой запрос к битемпоральному MV возвращает текущее состояние, восстановленное по журналу. Чтобы вернуться во времени, отправьте заголовок X-Provisa-As-Of: <timestamp>, и весь запрос получит ответ таким, каким были данные в тот момент, одинаково на любом хранилище. Добавьте X-Provisa-As-Recorded, чтобы прочитать данные такими, какими Provisa записал их на момент времени: тогда исправление, записанное позже, не изменит воспроизведение прошлого. Включите это для любого материализованного представления в интерфейсе администратора (элемент Time Travel: выкл., snapshot или delta плюс ключ сущности) или через API администратора.
Достижимость и актуальность вместе дают общую модель федерации: определение того, что живое, что копируется и насколько свежей остаётся каждая копия, независимо от того, до чего достаёт какой-либо движок. Модель переносима, поэтому ваши данные не привязаны к поставщику, чья федерация сегодня достаёт до большего числа источников.
Возможности¶
Интерфейсы запросов¶
Это языки и структурированные API, на которых вы пишете запросы. У каждого свой синтаксис и семантика; управление (RLS, маскирование, видимость столбцов, принуждение связей) применяется одинаково ко всем из них, независимо от того, каким проводным протоколом они доставлены.
- GraphQL — Схемы для каждой роли с видимостью на уровне полей, фильтрацией, курсорной пагинацией и агрегатными запросами (
count,sum,avg,min,max). Схема предлагает только зарегистрированные связи, поэтому любой запрос структурно корректен по построению, и GraphQL является самым быстрым путём к правильному простому запросу. Apollo APQ включён: запросы хэшируются и регистрируются на сервере, последующие вызовы отправляют только хэш через HTTP GET, и ответы становятся кэшируемыми в CDN без изменений в клиенте. Справочные таблицы ниже настраиваемого порога строк выглядят как типы enum. - SQL — Полноценный SQL над федеративными данными, без ограничений и выразительнее GraphQL. Пишите стандартный SQL, включая коррелированные подзапросы, и он выполняется по источникам без изменений. Запрос к одному источнику полностью минует слой федерации (менее 100 мс).
- Cypher — Язык графовых запросов поверх той же федеративной схемы. Обходите связи как рёбра графа; объединяйте источники; пути переменной длины. Управление применяется так же, как в GraphQL и SQL.
- Модельный API gRPC —
.proto, сгенерированный из зарегистрированной схемы, с типизированными RPC запроса и вставки для каждой таблицы в корне схемы роли и потоковыми ответами. Как и GraphQL, он управляется схемой: модель регистрации служит контрактом, а protobuf кодировкой передачи. Это полноценный интерфейс запросов для каждой таблицы, тогда как Arrow Flight является транспортом потоковой передачи по столбцам. - JSON:API — Структурированный API запросов по адресу
/data/jsonapi/{table}, только HTTP по замыслу. Поддерживает JSON:API 1.1: разреженные наборы полей (fields[table]=col1,col2), выражения фильтров (filter[field][op]=value), составные документы (include=relation) и сортировку. Он запрашивает одну таблицу за раз со стандартным синтаксисом фильтров, поэтому, если нужен язык запросов общего назначения, используйте SQL или GraphQL. - Обозреватель языков запросов — Напишите запрос GraphQL и смотрите живые переводы в Semantic SQL и Cypher в боковых панелях; скопируйте любой из них или перейдите прямо в редактор SQL или графа. Практичный приём — набросать фрагменты запроса на GraphQL, а затем сшить полученный SQL в сложные представления или отчёты.
Обозреватель показывает запрос GraphQL рядом с его живыми переводами в SQL и Cypher:

Та же федеративная схема показывается и как живой граф, с метками доменов и узлов, типами связей и обходами переменной длины:

Инструменты составления запросов¶
Эти инструменты помогают писать запросы на перечисленных выше языках. Сами они языками запросов не являются.
- Запрос на естественном языке — Конвейер NL→SQL/Cypher/GraphQL, работающий на Claude. Опишите простыми словами, что вам нужно, и конвейер напишет запрос на выбранном языке, с интерактивным циклом проверки до того, как что-либо выполнится.

Проводные протоколы¶
Это протоколы подключения. SQL, GraphQL и Cypher работают поверх них, и выбранный протокол не меняет ни интерфейс запросов, ни поведение управления.
- pgwire — Любой клиент PostgreSQL (psql, DBeaver, DataGrip, asyncpg, SQLAlchemy, pandas
read_sql) подключается по порту 5439 так, будто это сервер Postgres. Принимает только SQL. Применяется полный конвейер управления.pg_catalogиinformation_schemaотвечаются из каталога в памяти, так что обозреватели схем работают без обращения к федерации. TLS по желанию. - Bolt (Neo4j) — Любой клиент Neo4j (Neo4j Browser, Bloom, официальные драйверы) подключается по протоколу Bolt и выполняет Cypher по федеративному графу. Каждая роль, которой обладает пользователь, проявляется как база данных
provisa_<role>. То же управление, что и на любом другом транспорте. TLS по желанию. - Arrow Flight — Высокопроизводительная колоночная потоковая передача поверх gRPC; принимает на вход GraphQL или SQL. Неограниченные результирующие наборы, без материализации на сервере, без отдельной инфраструктуры.
- JDBC — Интеграция с BI-инструментами (Tableau, Power BI, DBeaver).
- WebSocket / SSE — Подписки: события изменений в режиме, близком к реальному времени; бэкенды: нативный PG, нативный MongoDB, CDC, опрос. Также выставляются через Kafka.
Источники данных¶
- 73 коннектора, более 85 видов источников — Большее число считает по отдельности размещённые сервисы PostgreSQL (RDS, Aurora, Cloud SQL, AlloyDB, Azure, Supabase, Neon) и форматы файлов File Crawler. PostgreSQL, MySQL, MongoDB, Cassandra, Elasticsearch, Neo4j, хранилища триплетов SPARQL, Kafka, Google Sheets, Kaggle, Salesforce, ServiceNow, Stripe и остальные доступны через единый API. Графовые и RDF-источники стоят наравне с реляционными.
- Умная маршрутизация — Запрос к одному источнику минует федерацию (менее 100 мс). Запрос к нескольким источникам идёт через слой федерации, на вашем собственном кластере или на встроенных воркерах.
- Источники API — Регистрируйте конечные точки REST, GraphQL, gRPC, WebSocket или RSS как запрашиваемые таблицы, вспомогательные средства SPARQL включены. Федеративные соединения между источниками API и реляционными источниками не требуют дополнительной настройки.
- Интроспекция удалённых схем — Укажите на любую конечную точку GraphQL, OpenAPI или gRPC; документированные операции автоматически выставляются как запрашиваемые таблицы, узлы и рёбра графа с полным управлением поверх
- Файловые источники — Файлы CSV, Parquet и SQLite как запрашиваемые таблицы; поддерживаются локальные пути и удалённые объектные хранилища (
s3://,ftp://,sftp://) - Интеграция с Kafka — Топики как таблицы только для чтения; результаты запросов как приёмники Kafka
- Планируемые триггеры — Триггеры по расписанию cron и по интервалу (APScheduler), запускающие веб-хуки, мутации или публикации в приёмник Kafka
- Подсказки производительности федерации — Подсказки маршрутизации в комментариях SQL переопределяют автоматические решения о маршрутизации

Источники, файлы и удалённые конечные точки регистрируются как управляемые таблицы из интерфейса:

Безопасность и управление¶
- Безопасность на уровне строк — Подстановка предложения WHERE на таблицу и на роль
- Маскирование столбцов — Маскирование на столбец (регулярное выражение, константа, усечение) с обходом по роли
- Предустановки столбцов — Серверные статические значения или значения переменных сессии, подставляемые при вставке/обновлении; не выставляются во входных типах мутаций
- Права на запись — Контроль доступа к мутациям на уровне столбца (
writable_by) - Наследуемые роли — Роли рекурсивно наследуют RLS, видимость и маскирование от родительской роли
- Учтённые функции и веб-хуки — Функции БД и исходящие веб-хуки, выставленные как мутации GraphQL с типизированными формами возврата
- Хук одобрения ABAC — Хук авторизации перед выполнением; транспорт webhook, gRPC или unix_socket; область на таблицу, на источник или глобальная; настраиваемая запасная политика
- Подключаемая аутентификация — Firebase, Keycloak, OAuth 2.0, простая (для тестирования)

Доставка и производительность¶
- Материализованные представления как записанные преобразования — MV записывает преобразование, которое её создало: форму соединения или SQL, входные сигналы по каждому источнику, из которых она построена (снимок Iceberg, watermark RDB), и проверку детерминизма при регистрации. Поскольку преобразование записано, Provisa может переписать запрос или его часть на свежую MV без изменения запроса с вашей стороны. Сопоставление идёт по шаблонам соединений и допускает частичное совпадение, поэтому MV, покрывающая часть соединений, всё равно применяется, а остальные соединения сохраняются.
- Встраивание горячих таблиц — Небольшие часто соединяемые справочные таблицы встраиваются как CTE со списком VALUES прямо в план запроса, устраняя межисточниковые обращения за данными измерений
- Кеширование запросов — Кеш результатов в Redis, разделённый по роли и RLS; кеш хешей APQ включён
- Наблюдаемость как данные — Распределённые трассировки, метрики и логи собираются через OpenTelemetry, уплотняются в Iceberg на S3 и регистрируются как запрашиваемые таблицы (
traces,metrics,logs,queries) в федеративной схеме. Запрашивайте их через SQL, GraphQL или Cypher рядом с бизнес-данными. Например, соедините таблицуcustomersсqueries, чтобы увидеть, кто что запускал и сколько это заняло.
Администрирование и интеграция¶
- Административный API — GraphQL по адресу
/admin/graphql; выгрузка и загрузка конфигурации, редактирование связей, одобрение запросов - Просмотр отчётов —
/admin/reportsперечисляет встроенные управленческие представления домена эксплуатации и любые зарегистрированные пользовательские отчёты; требует возможностиobservability - Предпросмотр таблицы — у каждой зарегистрированной таблицы есть управляемый просмотрщик данных с серверной постраничной выдачей, проталкиваемыми фильтрами, многоуровневой группировкой и экспортом в CSV
- GraphQL Voyager — Интерактивная визуализация схемы в области видимости роли в виде диаграммы «сущность — связь»
- Обнаружение связей с помощью LLM — Claude предлагает кандидатов во внешние ключи.
- Клиент Python —
pip install provisa-client; GraphQL/SQL → DataFrame, Arrow Flight → таблицы pyarrow, диалект SQLAlchemy, поддержка ADBC - Приём данных — Конечные точки HTTP для отправки событий в формате JSON на платформу
- Импорт из Hasura v2 / DDN — Преобразование метаданных Hasura v2 или YAML суперграфа DDN в конфигурацию Provisa
- Apollo Federation — Выставление Provisa как подграфа Apollo Federation v2
Схема в области видимости роли, представленная как диаграмма «сущность — связь» (GraphQL Voyager):

Связи регистрируются, одобряются и принуждаются как единственные легальные пути JOIN:

Модель безопасности¶
Именно здесь «на пути, который и так проходит каждый запрос» должно оправдаться. Provisa применяет одну многоуровневую модель безопасности к каждому языку запросов (GraphQL, SQL, Cypher) и каждому транспорту (REST, gRPC, Arrow Flight, JDBC, pgwire, Bolt, WebSocket), и ни один путь запроса её не обходит. Охват заложен в устройство, поэтому никому не нужно ничего помнить: добавьте источник, столбец или связь, и каждый уровень сразу применяется к ним, без дополнительной регистрации.
Уровни применяются по порядку, и запрос должен пройти каждый, прежде чем проверяется следующий.
Слой 0 — Фильтрация интроспекции¶
Схема и каталог, которые видит роль, содержат только таблицы из её списка domain_access и столбцы, прошедшие свои правила visible_to. Всё, что вне доступа роли, невидимо с самого начала: это нельзя запросить, нельзя получить в автодополнении и нельзя даже догадаться, что оно существует. Это касается схемы GraphQL, каталога SQL и обозревателя схемы в редакторе запросов.
Слой 1 — Публичный доступ¶
Таблицы в доменах без ограничения domain_access видны любой аутентифицированной учётной записи, без дополнительной настройки. Действительно публичные данные не требуют усилий.
Слой 2 — Доступ к домену¶
У каждой роли есть список domain_access из ID доменов, и запрос, затрагивающий таблицу вне этих доменов, отклоняется до выполнения. Это крупная граница владения: роль HR не доберётся до финансовых таблиц, как бы ни был написан SQL.
Слой 3 — Безопасность на уровне строк¶
После подтверждения доступа к домену в каждый SELECT во время выполнения добавляются предикаты WHERE для таблицы и роли, и они вычисляются по исходным данным. Региональный менеджер, запрашивающий общую таблицу заказов, видит только строки своего региона, даже при SELECT *.
Слой 4 — Видимость и маскирование столбцов¶
Столбцы, в списке visible_to которых нет запрашивающей роли, убираются из вывода. В столбцах с правилом маскирования значения заменяются через regex-скрытие, константу или усечение, прежде чем результаты покинут сервер. Маскирование действует в любом языке запросов и любом формате вывода.
Слой 5 — Защита предикатов¶
Маскированные столбцы отклоняются в предложениях WHERE и HAVING. Иначе вызывающий мог бы вычислить настоящее значение двоичным поиском в фильтре, хотя вывод замаскирован. Отказ происходит при разборе запроса, до какого-либо выполнения.
Управление связями¶
В SQL условие JOIN должно соответствовать зарегистрированной и одобренной связи между таблицами, а неодобренное соединение отклоняется. У каждой связи есть понятная причина и описание, которые объясняют людям и автономным агентам, зачем нужен этот путь. Это политика управления, а не жёсткая граница безопасности. Уровни 2–5 действуют при любой форме соединения, поэтому намеренный обход не раскрывает ничего, до чего роль не добралась бы двумя отдельными запросами, а каждая попытка записывается в журнал для аудита.
Ни одно недопустимое соединение никогда не выполняется на ваших данных. Роли управляются по умолчанию, а отказ от этого означает сознательно выдать право ignore_relationships роли, которой вы доверяете. OAuth-токен агента сопоставляется с ролью, поэтому агент получает те же уровни, что и человек. Каталоги данных с контекстным слоем говорят агенту, что ему следует делать; Provisa определяет, что он может делать.
Эти уровни складываются. У роли с доступом к доменам, RLS и маскированными столбцами активны все уровни сразу, потому что каждый уровень настраивается отдельно и применяется к любому запросу, затрагивающему управляемый объект.
Быстрый старт¶
macOS¶
- Скачайте Provisa-macOS.dmg (всегда последний выпуск)
- Перетащите Provisa.app в
/Applicationsи запустите двойным щелчком - Первый запуск выполняет разовую настройку (~2 мин, интернет не нужен)
- Откройте Терминал:
Linux¶
- Скачайте Provisa-linux-x86_64.AppImage (всегда последний выпуск)
- Сделайте файл исполняемым и запустите. Первый запуск выполняет разовую настройку (интернет не нужен):
chmod +x Provisa-*-linux-x86_64.AppImage
./Provisa-*-linux-x86_64.AppImage
provisa start && provisa open
Windows¶
- Скачайте Provisa-windows-x64.exe (всегда последний выпуск)
- Запустите установщик. Права администратора ему не нужны.
- Откройте Provisa First Launch из меню «Пуск». Он выполнит разовую настройку (~5 мин, интернет не нужен).
- Откройте новый терминал:
Первый запрос¶
При локальной разработке (PROVISA_MODE=test) учётные данные не нужны. В продакшене вы аутентифицируетесь токеном Bearer, и Provisa берёт роль из него.
# Local dev — no auth required, role defaults to admin
curl -X POST http://localhost:8001/data/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ orders { id amount region } }"}'
# Ad-hoc SQL works the same way
curl -X POST http://localhost:8001/data/graphql \
-H "Content-Type: application/json" \
-d '{"query": "SELECT id, amount, region FROM orders"}'
# Production — authenticate with a Bearer token; role is derived from the token
curl -X POST https://provisa.example.com/data/graphql \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query": "{ orders { id amount region } }"}'
JDBC (Tableau, DBeaver, Power BI)¶
Скачайте provisa-jdbc.jar (всегда последний выпуск) и добавьте его в путь к драйверам вашего BI-инструмента.
Аутентифицируйтесь своим именем пользователя и паролем Provisa, и сервер назначит вам роль.
Шаги настройки Tableau и Power BI см. в docs/integrations.md.
Проводной протокол PostgreSQL (pgwire)¶
Provisa говорит на сетевом протоколе PostgreSQL на порту 5439. Любой клиент, умеющий подключаться к Postgres, подключается к Provisa, без драйвера, без адаптера и без изменений в ваших инструментах.
Имя пользователя PostgreSQL выбирает роль Provisa. При provider: none (режим доверия) пароль игнорируется, и любое настроенное имя роли принимается как имя пользователя — подключитесь как analyst, admin или любая роль, чтобы увидеть управляемое представление данных для этой роли. При provider: simple пароль проверяется по bcrypt. Другие провайдеры (firebase, keycloak, oauth) по pgwire не поддерживаются.
# psql — connect as analyst role
psql -h localhost -p 5439 -U analyst
# psql — connect as admin role
psql -h localhost -p 5439 -U admin
# asyncpg (Python) — role = username, password ignored in trust mode
conn = await asyncpg.connect(host="localhost", port=5439, user="analyst", password="x")
rows = await conn.fetch("SELECT id, amount FROM orders WHERE region = 'west'")
# SQLAlchemy
engine = create_engine("postgresql+psycopg2://analyst:x@localhost:5439/provisa")
# pandas
df = pd.read_sql("SELECT * FROM orders", engine)
Каждый запрос проходит полный конвейер управления, поэтому доступ к доменам, RLS, маскирование и защита предикатов применяются точно так же, как для GraphQL и REST. Обозреватели схем (DBeaver, DataGrip, pgAdmin) работают без настройки. Provisa отвечает на их запросы к pg_catalog и information_schema из каталога в памяти, ограниченного доступом роли к доменам, поэтому пользователи видят только те таблицы и столбцы, которые им разрешено запрашивать.
DataGrip просматривает управляемую схему и её диаграмму внешних ключей через pgwire, без драйвера и без адаптера:

TLS включается заданием PROVISA_PGWIRE_CERT и PROVISA_PGWIRE_KEY. Порт настраивается через PROVISA_PGWIRE_PORT (по умолчанию 5439).
Bolt (проводной протокол Neo4j)¶
Provisa говорит и на протоколе Neo4j Bolt, поэтому графовые инструменты подключаются напрямую и выполняют Cypher над федеративным графом. Ничего не экспортируется, и отдельная графовая база не нужна. Направьте Neo4j Browser или Bloom на Provisa и обходите связи между источниками под тем же управлением (доступ к доменам, RLS, маскирование).
Здесь Neo4j Browser выполняет Cypher в Provisa. Метки узлов, типы связей и ключи свойств берутся прямо из зарегистрированной схемы:

Включите его, задав PROVISA_BOLT_PORT (по умолчанию у Neo4j это 7687), а TLS включите через PROVISA_BOLT_CERT и PROVISA_BOLT_KEY. Каждая роль Provisa, которую имеет аутентифицированный пользователь, видна как выбираемая база данных provisa_<role> (селектор provisa_admin выше). Выбор одной из них сужает сеанс до доменных прав этой роли, и пользователь никогда не выходит за пределы своих ролей.
Клиент Python¶
pip install provisa-client # core
pip install "provisa-client[pandas]" # + DataFrame support
pip install "provisa-client[sqlalchemy]" # + SQLAlchemy dialect
pip install "provisa-client[adbc]" # + ADBC over Arrow Flight
from provisa_client import ProvisaClient, connect
# GraphQL → DataFrame
client = ProvisaClient("http://localhost:8001", username="alice", password="secret")
df = client.query_df("{ orders { id amount region } }")
# SQL → DataFrame
df = client.query_df("SELECT id, amount, region FROM orders WHERE region = 'west'")
# Arrow Flight → pyarrow Table (high-throughput columnar)
table = client.flight("{ orders { id amount region } }")
# DB-API 2.0 (PEP 249) — GraphQL or SQL, detected automatically
with connect("http://localhost:8001", username="alice", password="secret") as conn:
cur = conn.cursor()
# GraphQL
cur.execute("{ orders { id amount region } }")
rows = cur.fetchall()
# SQL (routed through governance engine — RLS and masking applied)
cur.execute("SELECT id, amount FROM orders WHERE region = %s", ("west",))
rows = cur.fetchall()
# SQLAlchemy dialect — provisa+http:// or provisa+https://
from sqlalchemy import create_engine, text
import pandas as pd
engine = create_engine("provisa+http://alice:secret@localhost:8001")
# pandas read_sql — GraphQL or SQL
df = pd.read_sql("{ orders { id amount region } }", engine)
df = pd.read_sql("SELECT id, amount, region FROM orders WHERE region = 'west'", engine)
# raw execute
with engine.connect() as conn:
rows = conn.execute(text("SELECT id, amount FROM orders")).fetchall()
# role URL parameter
engine = create_engine(
"provisa+http://alice:secret@localhost:8001?role=analyst"
)
# ADBC — Arrow-native streaming via Flight
from provisa_client.adbc import adbc_connect
with adbc_connect("http://localhost:8001", user="alice", password="secret") as conn:
with conn.cursor() as cur:
cur.execute("{ orders { id amount } }")
table = cur.fetch_arrow_table()
Полный справочник см. в docs/python-client.md.
Документация¶
| Тема | Документ |
|---|---|
| Быстрый старт для разработчика (запуск из исходников) | docs/quickstart.md |
| Полный справочник по конфигурации YAML | docs/configuration.md |
| Справочник конечных точек (GraphQL, REST, Flight, gRPC) | docs/api-reference.md |
| Проектирование системы и карта компонентов | docs/architecture.md |
| Модель безопасности (RLS, маскирование, аутентификация) | docs/security.md |
Хранение секретов и ссылки ${secret:NAME} |
docs/secrets.md |
| Бизнес-глоссарий и курирование терминов | docs/glossary.md |
| Окружения (dev / staging / prod) | docs/environments.md |
| Создание тестовых окружений (профилирование, поддельные данные, синтетические данные) | docs/test-data.md |
| Справочник методов поддельных данных | docs/fake-methods.md |
| Запуск и сборка демо на ноутбуке (инженеры по продажам) | docs/sales-engineer-demos.md |
| Поддерживаемые типы источников | docs/sources.md |
| Подписки SSE | docs/subscriptions.md |
| JDBC, BI-инструменты, клиенты Arrow Flight, Apollo Federation | docs/integrations.md |
Клиент Python (provisa-client) |
docs/python-client.md |
| Административный API | docs/admin.md |
| Развёртывание (Docker Compose, Kubernetes, macOS) | docs/deployment.md |
| Импорт из Hasura v2 / DDN | docs/import.md |
| Процесс выпуска (теги alpha/beta/stable) | docs/releasing.md |
Подбор мощности¶
В состав Provisa входит встроенный федеративный движок для многоисточниковых запросов. При первом запуске вы выбираете бюджет оперативной памяти; Provisa автоматически выводит число локальных рабочих процессов федерации.
| ОЗУ узла | Рабочие процессы | Типичная нагрузка |
|---|---|---|
| < 24 ГБ | 0 | Разработка, односточниковые запросы, небольшие команды |
| 24–47 ГБ | 1 | Небольшая команда, умеренные межисточниковые запросы |
| 48–95 ГБ | 2 | Развёртывание уровня отдела, смешанное использование BI и блокнотов |
| 96 ГБ+ | 4 | Крупный отдел, интенсивная параллельная федерация |
Число рабочих процессов можно изменить в любой момент, отредактировав ~/.provisa/config.yaml (federation_workers: N) и выполнив provisa restart. Значение 0 запускает только координацию (один узел).
Масштабирование за пределы одной машины¶
Горизонтальное масштабирование — Запустите несколько экземпляров Provisa за балансировщиком нагрузки. Каждый экземпляр является полной системой. Все экземпляры должны указывать на одну и ту же базу конфигурации (задайте CONFIG_DB_HOST на вторичных машинах) и могут делить один экземпляр Redis (REDIS_URL) для общего кэша. Большинство запросов распределяется без изменений. Очень большое соединение между источниками может не поместиться в один экземпляр, и тогда нужна машина помощнее или внешний кластер федерации.
Общий Redis — Задайте REDIS_URL на каждом экземпляре, указав на внешний Redis. Общий Redis означает, что записи кеша с одного экземпляра доступны всем, что повышает долю попаданий по кластеру.
Собственный федеративный кластер — Направьте Provisa на существующий внешний федеративный кластер вместо встроенных рабочих процессов. Рекомендуется для крупномасштабных или облачных развёртываний; о настройке см. docs/deployment.md.
Лицензия¶
Business Source License 1.1 (без изменений, согласно обязательствам лицензиара MariaDB). Каждая выпущенная версия переходит под изменённую лицензию (GPL v2.0 или новее) на 4-ю годовщину своего публичного выпуска; текущий и недавний код остаётся под BSL. Продуктивное использование сверх порогов дополнительного разрешения на использование (менее 100 сотрудников/подрядчиков и менее $1 млн выручки за предыдущий год) требует коммерческой лицензии. См. LICENSE.
Лицензиар не даёт согласия на использование этой работы для обучения моделей ИИ/машинного обучения. См. NOTICE, ai.txt и robots.txt. По вопросам коммерческих лицензий или лицензий на обучение ИИ: kennethstott@gmail.com