Provisa¶
Подключите свои базы данных. Запрашивайте через GraphQL, gRPC, SQL или MCP — поверх любого API или протокола — за 5 минут.
Provisa обслуживает любую поверхность API (REST, GraphQL, SQL, gRPC, MCP и другие) поверх объединённого результата по всем вашим источникам. Она может это делать, потому что является активным семантическим слоем: единым определением вашего хозяйства данных — каждый домен, связь и политика по всем источникам, за исключением только самих систем-первоисточников, — которое и управляет этим хозяйством, и руководит им. Это определение не документация, к которой движок может обратиться; оно и есть движок. Зарегистрированные домены и связи — единственные легальные пути соединения, а политики доступа компилируются в каждый план запроса. Одна модель, три задачи:
- Определение — Домены, столбцы и связи объявляются один раз. Это объявление и есть схема, которую видит каждый потребитель, и единственный набор путей соединения, доступный любому запросу.
- Принуждение — Безопасность на уровне строк, маскирование столбцов, видимость столбцов и одобрение запросов применяются встроенно на пути выполнения. Ни один запрос не доходит до данных, минуя их, так что покрытие полно по построению, а не по прилежанию.
- Аудит — Поскольку каждый запрос идёт по одному и тому же управляемому пути, кто, что, под какой ролью и против какой политики запросил, записывается единообразно. Распределённые трассы, метрики и журналы сами зарегистрированы как запрашиваемые таблицы рядом с вашими бизнес-данными.
Одно управляемое ядро обслуживает любой язык и транспорт. Запрашивайте через GraphQL, Cypher или SQL; потребляйте по pgwire, Bolt, gRPC, REST, Arrow Flight или JDBC. Каждый язык запросов понижается до единого промежуточного представления, куда управление внедряется однократно, — так что политика не может разойтись между языками, — и это IR перенацеливается на нативный диалект каждого источника на выходе. Добавление языка — это новый фронтенд к общему ядру, а не новый движок.
Хозяйство одновременно аналитическое и транзакционное. Межисточниковые чтения разлетаются через уровень федерации; записи и односточниковые чтения направляются напрямую в драйвер источника — управляются идентично, но транзакционно и менее чем за 100 мс. Колоночная потоковая передача Arrow Flight встроена.
Вся модель построена из горстки примитивов — домены, связи, роли и политики. Небольшой словарь, поэтому определение легко осмыслить и просто оценить и проверить: можно прочитать набор политик и понять, что он делает. Provisa — лёгкий компилятор запросов, а не среда выполнения, сидящая на пути данных. Она превращает запрос в нативные запросы, направляет их и уходит с дороги — поэтому хозяйство и работает быстро.
Такая конструкция поддерживает два способа применения, и они не исключают друг друга:
- Как леса для модернизации — Смоделируйте хозяйство, дайте Provisa сгенерировать нативный SQL для каждого источника, затем захватите этот SQL и примите его прямо в целевой системе. Provisa — переходный слой, а не постоянная зависимость.
- Как постоянная инфраструктура принуждения политик — Оставьте её на месте как управляемый путь, по которому идёт каждый запрос, чтобы определение, принуждение и аудит оставались едиными столько, сколько существует хозяйство.
Модель федерации¶
Вся модель сводится к двум контрактам и двум политикам: источники сводятся к двумерным таблицам поверх одной системы типов, запросы сводятся к одному SQL-подобному IR, достижимость решает, что запрашивается вживую, а что материализуется, и стратегия свежести управляет каждой материализованной копией и производным набором данных. Форма данных на входе, форма запроса на входе, управление в точке соединения, нативные запросы на выходе. Дальше в этом разделе разбирается каждая часть.
Модель опирается на одну редукцию: каждый источник выражается как набор двумерных таблиц поверх единой обобщённой системы типов. Это контракт, которому источник должен соответствовать, чтобы войти в хозяйство, и он один и тот же для всех. Некоторые источники подходят сразу — таблица MySQL или PostgreSQL и есть типизированное двумерное отношение. Некоторые подходят через проекцию: результат запроса GraphQL, будучи уплощённым, — это таблица. Некоторые чужды этой форме — хранилища триплетов SPARQL, Neo4j, — но остаются работоспособными, потому что пользователь задаёт запрос, чей результирующий набор табличен; запрос и есть адаптер. Каков бы ни был источник, хозяйство видит строки, столбцы и обобщённые типы, и ничего больше. Подключение нового вида источника — это выполнение того самого единственного контракта, иногда с шагом человеческого вмешательства, а не написание особой интеграции.
У этой редукции есть двойник на стороне запроса. SQL — со всеми его диалектами и причудами — по сути язык анализа над двумерными наборами данных, что делает SQL-подобную форму естественной универсальной целью для запросов. Поэтому каждый запрос, на каком бы языке он ни пришёл, самым первым шагом понижается до этого промежуточного представления. Некоторые понижаются чисто — сам SQL и даже GraphQL; некоторые тяжело — семантика путей и графов в Cypher требует настоящей работы, — но все выполнимы. Пропуск каждого запроса через одно IR прежде всего остального и есть то, что позволяет применять управление ровно в одном месте, к одной форме, независимо от языка, на котором он пришёл.
Поверх этих двух однородных форм — табличных источников и единой формы запроса — федерация здесь означает и живой запрос, и складирование — тот же охват, который покрывает движок живых запросов вроде Trino, плюс материализация, на которую такие движки опираются. Понятие, объединяющее их, — достижимость: может ли движок для данного источника запросить его на месте, или его данные сперва должны быть материализованы где-то, где их можно запросить? Достижимость делит хозяйство на то, что запрашивается вживую, и то, что предварительно копируется.
Большинство баз данных уже несут некоторое понятие живой связи — DuckDB ATTACH, PostgreSQL postgres_fdw, внешние ссылки Databricks. Так что большинство баз данных в той или иной мере способны выступать федеративным движком. Ни один не всеобъемлющ: каждый достаёт до определённого набора источников и материализует остальные, без единого учёта того, что именно к чему относится. Модель закрывает этот пробел, делая достижимость явной: определённый набор методов на каждый источник, который говорит, до чего движок дотягивается вживую и, по исключению, что должно быть материализовано.
Остаётся свежесть: насколько актуальной должна быть материализованная копия каждого недостижимого источника? На практике это сводится к небольшому набору стратегий — по требованию, по расписанию, по сигналу изменения (CDC, водяной знак, снимок) или закреплённая. Выбор одной из них на источник — и есть вся политика свежести.
Аналитические наборы данных — производные таблицы, агрегаты, результаты преобразования — укладываются в ту же форму. Они тоже должны быть выражены в IR, и потому происхождение данных не является отдельной системой, которую надо поддерживать: путь от каждой системы-первоисточника до конечного результата и есть то IR, которое его породило, читаемое от начала до конца. Их построение поднимает вопрос свежести на шаг дальше: обновляется ли набор данных по расписанию, только по выполнении его предусловий, непрерывно в режиме, близком к реальному времени, или как закреплённый исторический снимок? Способы выразить, как и когда строить набор данных, — тот же небольшой перечислимый набор, так что производный набор данных несёт политику построения ровно в том же словаре, что и копия источника.
Размерностные модели — прямое применение этого. Таблицы фактов и измерений схемы «звезда» — такие же аналитические наборы данных, как любые другие: измерение — это согласованная, дедуплицированная проекция; таблица фактов — соединение и агрегат, сведённые к гранулярности, — каждая со своей политикой построения и свежести. Медленно меняющиеся измерения не требуют особой машинерии: закреплённый снимок — это история типа 2, плановая перестройка — тип 1. А поскольку схема определена в IR, а не физически привязана к таблицам одного хранилища, те же определения фактов и измерений перенацеливаются — материализуются в Oracle, в Databricks или остаются виртуальными поверх MPP-движка — без перемоделирования. Модель порождает схему «звезда»; она не привязывает её к движку.
Data Vault укладывается так же, одним слоем раньше. Его хабы — дедуплицированные наборы данных бизнес-ключей, его линки — зарегистрированные связи между ними, а его сателлиты — наборы данных атрибутов только на вставку с отметкой времени, то есть исторический учёт. Сателлит — это просто производный набор данных на стратегии свежести по сигналу изменения: дата загрузки плюс hashdiff — это CDC, применённый к описательным атрибутам, а история только на вставку — стратегия закреплённого снимка. Таблицы point-in-time и bridge — дальнейшие производные наборы данных, построенные ради производительности запросов. Так что сырое хранилище — набор аналитических наборов данных в IR, а схема «звезда» — проекция от него; оба порождены, оба переносимы между движками. Чего модель не делает, так это не решает за вас методологию: что становится хабом, гранулярность сателлита, стратегию разбиения. Это остаётся выбором моделирования; будучи сделанным, он живёт как переносимое IR, а не как ETL, приваренный к одному хранилищу.
Оба паттерна объявляются через два полноправных сокращения, а не через рукописные представления, — примитивы, из которых строится любая схема «звезда» и любой Data Vault, оставленные нейтральными к методологии:
entity— ключевая, дедуплицированная, опционально историзируемая проекция источника. Объявите ключ сущности, атрибуты и режим истории; Provisa понижает это до материализованного представления, а когда запрошена история — до битемпорального MV (scd2→ дельта,snapshot→ снимок). Одна конструкция обслуживает измерение по Кимбаллу (SCD1/SCD2) и хаб + сателлит Data Vault.fact— соединение по ключам сущностей, сведённое к объявленной гранулярности, с агрегированными мерами. Provisa понижает это до агрегирующего MV плюс зарегистрированных связей с сущностями. Одна конструкция обслуживает таблицу фактов звезды и линк Data Vault (факт без мер — чистый линк из множества ключей).
Поскольку понижение чистое — спецификация entity/fact становится ровно теми определениями MV, битемпоральности и связей, которые моделировщик иначе написал бы вручную, — хранилище есть IR до самого низа и перенацеливается между движками без перемоделирования. Объявите хранилище в административном интерфейсе (форма Model для сущностей и фактов) или через административный API (registerEntity / registerFact); модель порождает звезду Кимбалла или Data Vault, а не навязывает какой-то один.
Путешествие во времени¶
Путешествие во времени — простая идея: хранить каждую версию строки вместо её перезаписи, чтобы можно было спросить, какими данные были в любой прошлый момент. Различается лишь то, насколько эффективно это может сделать каждый движок, и именно поэтому Provisa делает это свойством определения материализованного представления, а не свойством движка хранения (REQ-1162). Объявите один раз; это работает на любом материализующем бэкенде.
Правило, которое сохраняет переносимость, — только добавление: однажды записанная версия никогда не обновляется и не удаляется. Вывод строки из обращения записью даты «действительно по» — обычный битемпоральный приём — требует UPDATE, который многие движки не могут выполнить дёшево (или вообще) поверх федеративного хранилища, поэтому Provisa так не делает. Вместо этого каждое обновление добавляет, а «какая версия действовала в момент T» выводится при чтении из неизменяемого журнала. Способов добавления ровно два:
- Снимок — добавить весь свежий набор данных, отмеченный системным временем этого обновления. Никакого вычисления разниц; корректно на каждом движке; объём растёт на полную копию за обновление.
- Дельта — добавить только изменившееся плюс метки-надгробия для удалённых ключей. Дельта вычисляется движком (антисоединения внутри
INSERT … SELECT), а не сворачивается построчно в Provisa. Компактнее, и требует ключа сущности.
Системное время (когда Provisa записала версию) управляется этим способом; действительное время (когда факт истинен в бизнесе) поставляется собственным SELECT представления и сохраняется. Движки, предлагающие больше — нативные снимки Iceberg, MERGE, поддерживающий меньше строк, — могут быть выбраны ради эффективности за тем же объявлением; путь «только добавление» — это нижняя планка, корректная везде.
Чтение прозрачно. Обычный запрос к битемпоральному MV по умолчанию восстанавливает текущее состояние из журнала добавлений; чтобы отправиться во времени, пришлите заголовок X-Provisa-As-Of: <timestamp>, и весь запрос будет отвечен так, каким хозяйство было в тот момент, — идентичная семантика на любой подложке. Включите это для любого материализованного представления в административном интерфейсе (элемент Time Travel: выкл. / снимок / дельта плюс ключ сущности) или через административный API.
Достижимость плюс свежесть — это общая модель федерации данных: определение, которое говорит, что живое, что материализовано и насколько свежей остаётся каждая копия, — независимо от охвата какого-либо одного движка. Итог — свобода от проприетарной привязки. Модель переносима; хозяйство не в плену у того вендора, чья федерация сегодня дотягивается до наибольшего числа источников.
Возможности¶
Интерфейсы запросов¶
Это языки и структурированные API, на которых вы пишете запросы. У каждого свой синтаксис и семантика; управление (RLS, маскирование, видимость столбцов, принуждение связей) применяется одинаково ко всем из них, независимо от того, каким проводным протоколом они доставлены.
- GraphQL — Схемы на роль с видимостью на уровне полей, фильтрацией, курсорной пагинацией и агрегирующими запросами (
count,sum,avg,min,max). Ограничена схемой до зарегистрированных связей — структурно корректна по построению, самый быстрый путь к правильному простому запросу. Apollo APQ включён: запросы хешируются и регистрируются на сервере; последующие вызовы шлют только хеш по HTTP GET, что делает ответы кешируемыми на CDN без единого изменения на клиенте. Справочные таблицы ниже настраиваемого порога числа строк выставляются как перечисляемые типы. - 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) и сортировку. Не язык запросов общего назначения — запрашивает по одной таблице за раз стандартизованным синтаксисом фильтров, а не произвольной строкой запроса. - Обозреватель языков запросов — Напишите запрос 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) в режиме
approvedилиcatalog. - WebSocket / SSE — Подписки: события изменений в режиме, близком к реальному времени; бэкенды: нативный PG, нативный MongoDB, CDC, опрос. Также выставляются через Kafka.
Источники данных¶
- 53 типа источников — PostgreSQL, MySQL, MongoDB, Cassandra, Elasticsearch, Neo4j, хранилища триплетов SPARQL, Kafka, Google Sheets и другие через единый 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, водяной знак РБД), из которых оно построено, и проверку детерминизма при регистрации. Поскольку преобразование записано, запросы (или подвыражения) прозрачно переписываются на свежее 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 из идентификаторов доменов. Запрос, затрагивающий таблицу вне этих доменов, отклоняется до выполнения. Это грубая граница владения — роль отдела кадров не дотянется до финансовых таблиц, как бы ни был написан SQL.
Слой 3 — Безопасность на уровне строк¶
После подтверждения доступа к домену предикаты WHERE, заданные на таблицу и на роль, подставляются в каждый SELECT во время выполнения. Предикаты вычисляются по сырым данным. Региональный руководитель, запрашивающий общую таблицу заказов, видит только строки своего региона, даже при SELECT *.
Слой 4 — Видимость и маскирование столбцов¶
Столбцы, чей список visible_to исключает запрашивающую роль, вырезаются из вывода запроса. У столбцов с правилом маскирования значения заменяются — сокрытие по регулярному выражению, замена константой или усечение — до того, как результаты покинут сервер. Маскирование применяется во всех языках запросов и форматах вывода.
Слой 5 — Защита предикатов¶
Маскированные столбцы отклоняются в предложениях WHERE и HAVING. Без этого вызывающий мог бы вывести немаскированное значение двоичным поиском по фильтру, даже если вывод замаскирован. Отклонение принуждается на этапе разбора запроса, до выполнения.
Управление связями¶
Условия JOIN в SQL должны соответствовать зарегистрированной, одобренной связи между таблицами. Неодобренные соединения отклоняются. Каждая связь несёт понятные человеку обоснование и описание — ориентир и для пользователей, и для автономных агентов, зачем существует этот путь обхода. Это политика управления, а не жёсткая граница безопасности: слои 2–5 держатся независимо от структуры соединения, поэтому намеренный обход не откроет данных, до которых роль не смогла бы дотянуться двумя отдельными запросами. Попытки обхода журналируются и поддаются аудиту.
Эти слои складываются. У роли с доступом к домену, 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 — роль извлекается из него автоматически.
# 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 — сервер назначит вашу роль.
- Режим
catalog— видна вся схема; используйте с каталожными инструментами (Collibra, Atlan, DBeaver)
Шаги настройки 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) работают сразу: запросы к 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 + mode URL parameters (mode=catalog for arbitrary SQL)
engine = create_engine(
"provisa+http://alice:secret@localhost:8001?role=analyst&mode=catalog"
)
# 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/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