Vai al contenuto

Tipi di origine

Modello di esecuzione

Ogni query viene infine eseguita attraverso il motore di federazione, che fornisce federazione su tutte le origini. Le origini rientrano in tre categorie in base alla loro connettività. [tool-verified: provisa/core/models.py lines 84–132] (REQ-550)

Categoria Ha driver diretto Ha connettore federato Esempi
Direct-capable PostgreSQL, MySQL, MariaDB, SingleStore, SQL Server, Oracle, DuckDB
Solo federazione No Redshift, Druid, Exasol, Hive, Iceberg, Delta Lake, Hive (basato su S3)
Direct-read (replica) Snowflake, Databricks, ClickHouse — il driver legge i dati e atterra una replica; le query girano contro la replica nel motore attivo
Materializza → Federazione No No REST/OpenAPI, GraphQL remoto, gRPC, Neo4j Cypher, SPARQL, WebSocket, RSS, CSV, SQLite, Parquet, Ingest (ricevitore push), GovData, SharePoint, Splunk

Le origini Direct-capable eseguono query a singola origine tramite il loro driver nativo (sub-100ms), bypassando il motore di federazione (REQ-027, REQ-229). Mantengono il pieno supporto del connettore e partecipano alla federazione quando unite ad altre origini (REQ-028).

Le origini Solo federazione vengono sempre interrogate attraverso il layer di federazione. Non esiste un driver diretto (REQ-229).

Le origini Direct-read (replica) hanno un DirectDriver che legge dal warehouse nativamente (Arrow-native dove disponibile), atterra una replica nello store di materializzazione del motore attivo, e poi le query girano contro quella replica. Vedi Warehouse come origini nominate.

Le origini Materialize non hanno un connettore federato. Provisa recupera i loro dati (all'avvio o al momento della query) e li mette in cache come Parquet su S3 o in PostgreSQL, rendendoli raggiungibili dal motore di federazione per query cross-source (REQ-309).


Tutte le origini

Riferimento per ogni tipo di origine supportato da Provisa. "Driver diretto" significa che le query a singola origine vengono eseguite nativamente contro l'origine (sub-100ms) (REQ-027). "Nome connettore" è il connettore federato usato quando l'origine partecipa a JOIN multi-source (REQ-028). [tool-verified: provisa/core/source_registry.py SOURCE_TO_DIALECT; provisa/federation/trino_connectors.py trino_connector_name]

RDBMS

Tipo di origine Driver diretto Nome connettore Dialetto Mutation
postgresql asyncpg postgresql postgres
mysql aiomysql mysql mysql
mariadb aiomysql mariadb mysql
singlestore singlestore singlestore Federata
sqlserver aioodbc sqlserver tsql
oracle oracledb oracle oracle
duckdb duckdb memory duckdb
cockroachdb asyncpg (pg wire) postgresql postgres
yugabytedb asyncpg (pg wire) postgresql postgres
greenplum asyncpg (pg wire) postgresql postgres
tidb aiomysql (mysql wire) mysql mysql

I database wire-compatible riusano il driver JDBC, il driver async nativo e il dialetto di un wire di base — CockroachDB, YugabyteDB e Greenplum usano il wire PostgreSQL; TiDB usa il wire MySQL. Richiedono solo voci di registro, nessun nuovo codice connettore. [tool-verified: provisa/core/source_registry.py _PG_WIRE_TYPES, _MYSQL_WIRE_TYPES] (REQ-950)

firebird (Firebird 3/4/5) e airport (server Arrow Flight) sono tipi di origine registrati, raggiunti in loco tramite estensioni community di DuckDB quando DuckDB è il motore attivo — nessun driver diretto, nessun connettore federato. [tool-verified: provisa/core/models.py lines 44, 93] (REQ-899)

Data warehouse cloud

[tool-verified: executor/drivers/snowflake.py, executor/drivers/databricks.py, executor/drivers/registry.py]

Tipo di origine Driver diretto Nome connettore Dialetto Mutation Note
snowflake SnowflakeDriver snowflake snowflake Federata Legge via snowflake-connector-python; atterra una replica; account/warehouse/role in federation_hints (REQ-988)
bigquery bigquery bigquery Federata Nessun DirectDriver; raggiunta via motore di federazione o ATTACH del motore BigQuery
databricks DatabricksDriver delta_lake databricks Federata Legge via databricks-sql-connector (Cloud Fetch, Arrow); atterra una replica; http_path richiesto in federation_hints (REQ-987)
redshift redshift redshift Federata
fabric MssqlWarehouseDriver tsql Federata Microsoft Fabric Warehouse; T-SQL su TDS, auth Azure AD; atterra una replica (REQ-995)
synapse MssqlWarehouseDriver tsql Federata Azure Synapse SQL; T-SQL su TDS, auth Azure AD; atterra una replica (REQ-995)
trino SQLAlchemyDriver Federata Coordinator Trino/Presto remoto letto via il dialetto SQLAlchemy trino; atterra una replica su qualsiasi motore (REQ-994)

Analytics / OLAP

[tool-verified: executor/drivers/clickhouse.py]

Tipo di origine Driver diretto Nome connettore Dialetto Mutation Note
clickhouse ClickHouseDriver clickhouse clickhouse Federata Legge via clickhouse-connect (HTTP); secure: "true" in federation_hints per TLS (REQ-986)
druid druid druid No
exasol exasol exasol No
elasticsearch elasticsearch No Le proprietà del connettore provengono dal DSL di mapping del tipo [tool-verified: trino_connectors.py:309]
pinot pinot No Connettore Trino pinot; pinot.controller-urls = host:porta del controller Pinot [tool-verified: trino_connectors.py:199]

Data Lake / formati tabella aperti

Questi tipi di origine sono solo-federazione — nessun driver diretto, nessun dialetto. [tool-verified: LAKE_ONLY_SOURCES in provisa/core/source_registry.py] (REQ-229)

Tipo di origine Nome connettore Time Travel Note
iceberg iceberg Sì (argomento as_of, REQ-372)
delta_lake delta_lake Sì (argomento as_of, REQ-372)
hive hive No
hive_s3 hive No Hive basato su S3

NoSQL

mongodb, cassandra e redis hanno connettori Trino (redis costruisce le sue proprietà dal DSL di mapping del tipo). [tool-verified: provisa/federation/trino_connectors.py; provisa/core/models.py] (REQ-017, REQ-1097)

Tipo di origine Nome connettore Mutation
mongodb mongodb No
cassandra cassandra No
redis redis No

Streaming

Tipo di origine Meccanismo Mutation
kafka Connettore Kafka federato; schema via Confluent Schema Registry (Avro, Protobuf, JSON Schema), definizione manuale, o inferenza da campione (REQ-147, REQ-150) Solo sink (REQ-176)
websocket Feed WebSocket esterno — connette, si iscrive, riceve eventi; risultati materializzati (REQ-338) No
rss Feed RSS 2.0 / Atom — polling, watermark per pubDate/updated; risultati materializzati (REQ-342, REQ-343) No

Ricevitore push

Tipo di origine Meccanismo Mutation
ingest Servizi esterni inviano eventi JSON via POST; risultati materializzati (REQ-331, REQ-335) No

Grafo e semantico

Tipo di origine Meccanismo Mutation
neo4j Cypher via API HTTP, risultati messi in cache in PostgreSQL (REQ-295) No
sparql SPARQL 1.1 POST, risultati messi in cache in PostgreSQL (REQ-297) No

Basate su file

Due meccanismi coprono i file. Entrambi usano il campo path invece di host/port. [tool-verified: provisa/core/models.py] (REQ-553)

Origini a file singolosqlite, csv, parquet puntano path su un singolo file.

Tipo di origine Trasporti Mutation
sqlite locale
csv locale No
parquet locale, s3:// No

I bucket privati richiedono credenziali (regione AWS e chiavi dall'ambiente). Per CSV su s3:// o http(s)://, o per registrare molti file contemporaneamente, usa l'origine files. [tool-verified: provisa/file_source/source.py]

Origine files — punta path su un glob, lo esegue in crawling ricorsivamente, e registra la directory come catalogo federato di tabelle. Legge molti formati su molti trasporti; gli insiemi sotto provengono dal connettore file (fork kenstott/calcite). [tool-verified: provisa/core/catalog.py files branch e provisa/core/models.py SOURCE_TO_CONNECTOR; liste di formati e trasporti dall'adapter calcite fileFileSchema.java, storage/StorageProviderFactory.java]

Formati Trasporti
CSV, TSV, JSON, YAML, Excel (XLS/XLSX), Parquet, Arrow, e documenti convertiti in tabelle — HTML, Markdown, DOCX, PPTX Filesystem locale, HTTP(S), s3://, hdfs://, ftp:///ftps://, sftp://, iceberg://, SharePoint (REST e Microsoft Graph)
- id: sales_files
  type: files
  path: s3://bucket/sales/**/*.csv   # glob; local and http(s):// also supported

Osservabilità e altro

prometheus ha un connettore Trino (proprietà costruite dal DSL di mapping del tipo). google_sheets è un tipo di origine registrato senza connettore Trino e materializza attraverso la pipeline di cache API. [tool-verified: provisa/federation/trino_connectors.py:314; provisa/core/models.py lines 87–88]

Tipo di origine Nome connettore Mutation
google_sheets — (materializzata) No
prometheus prometheus No

Connettori SaaS enterprise

SharePoint e Splunk si registrano tramite connettori Apache Calcite (fork kenstott/calcite). Nessuno dei due ha un driver diretto — Provisa materializza le loro righe avviando il server pgwire Calcite integrato del connettore (pgwire-sharepoint, pgwire-splunk), connettendosi a esso come endpoint PostgreSQL generico, e atterrando le righe nello store di materializzazione per la federazione (REQ-954). Entrambi i connettori abilitano sempre il matching dei nomi case-insensitive, corrispondente alla semantica case-insensitive propria di ciascun prodotto (REQ-725, REQ-730). [tool-verified: provisa/core/models.py lines 99–100; provisa/federation/trino_connectors.py lines 223–286]

sharepoint

Le liste SharePoint vengono enumerate come schemi ed esposte come tabelle interrogabili (REQ-726, REQ-731). Due metodi di autenticazione: CLIENT_CREDENTIALS (default) e basato su certificato tramite un certificato PFX (REQ-727). I valori segreti in mapping vengono risolti attraverso il motore dei secret prima di raggiungere il connettore (REQ-729). [tool-verified: provisa/federation/trino_connectors.py lines 230–252]

Campo origine Proprietà connettore Note
base_url o host site-url URL del sito SharePoint
username client-id Client ID dell'app Azure
password client-secret Client secret dell'app Azure
database tenant-id UUID del tenant Azure
mapping.auth_type auth-type CLIENT_CREDENTIALS (default) o CERTIFICATE
mapping.certificate_path certificate-path Percorso PFX quando auth_type: CERTIFICATE
mapping.certificate_password certificate-password Password PFX

Quando il connettore non espone information_schema.columns, registra la tabella con definizioni di colonna esplicite (ottenute dall'API Microsoft Graph) tramite la mutation registerTable (REQ-732).

- id: hr-sharepoint
  type: sharepoint
  base_url: https://kenstott.sharepoint.com
  username: ${env:SP_CLIENT_ID}
  password: ${env:SP_CLIENT_SECRET}
  database: ${env:SP_TENANT_ID}
  mapping:
    auth_type: CLIENT_CREDENTIALS

splunk

I risultati di ricerca Splunk sono interrogabili come tabelle (es. internal_server) (REQ-721). L'URL del connettore proviene da base_url, oppure viene costruito come https://{host}:{port} con porta di default 8089 (REQ-722). Auth: quando mapping.use_token è true (default), password viene passata come token API; quando false, username e password vengono passate come credenziali separate (REQ-723). [tool-verified: provisa/federation/trino_connectors.py lines 262–286]

Campo origine Proprietà connettore Note
base_url / host + port url base_url, altrimenti https://host:port (porta default 8089)
password token o password token quando use_token: true
username user solo quando use_token: false
database app restringe a un'app Splunk
mapping.datamodel_filter datamodel-filter filtra a un data model
mapping.disable_ssl_validation disable-ssl-validation per certificati self-signed (REQ-724)
- id: ops-splunk
  type: splunk
  host: splunk
  port: 8089
  password: ${env:SPLUNK_TOKEN}
  mapping:
    use_token: true
    disable_ssl_validation: true

Origini API

Registra qualsiasi endpoint HTTP come tabella interrogabile. [tool-verified: provisa/core/models.py SourceType enum] (REQ-314, REQ-307, REQ-322)

Tipo API Discovery Inferenza colonne
openapi Parsing della spec OpenAPI (REQ-314, REQ-316) Primitivi → nativo, oggetti → JSONB
graphql_remote Introspezione dello schema (REQ-307, REQ-308) Primitivi → nativo, oggetti → JSONB
grpc_remote Server reflection (REQ-322, REQ-325) Primitivi → nativo, oggetti → JSONB

Le risposte API vengono recuperate, messe in cache in PostgreSQL (TTL configurabile), ed esposte come tipi GraphQL (REQ-309, REQ-318, REQ-327). Le tabelle in cache partecipano a query federate come qualsiasi altra origine (REQ-313).

Regole JSONB: Le colonne complesse (oggetti, array) memorizzate come JSONB non sono filtrabili (REQ-119). L'accesso ai sotto-campi usa l'estrazione ->> in SQL (REQ-151). Le relazioni vengono dichiarate tra tabelle usando colonne FK scalari — le colonne blob JSONB non sono target di join. Usa la promozione JSONB per convertire campi annidati in colonne scalari native quando è necessario filtrare o unirsi su di essi (REQ-119).

GovData

Dati aperti del governo statunitense. L'accesso è partizionato per raggruppamento subject. [tool-verified: provisa/core/models.py lines 543–609]

Ogni origine govdata seleziona un subject. Quel subject determina quali schemi GovData vengono esposti. Gli schemi ref e geo sono sempre inclusi come schemi linker — non sono elencati per subject ma sono sempre presenti. [tool-verified: provisa/core/models.py line 562–563 comment]

Subject Schemi esposti
COMMERCE sec, patents
ECONOMY econ
EDUCATION census, edu
HEALTH health
CYBER cyber_threat, cyber_vuln
PUBLIC_SAFETY crime
ENVIRONMENT lands
WEATHER weather
GOVERNMENT fedregister, fec
ALL Ogni schema sopra elencato
sources:

  - id: federal-commerce
    type: govdata
    subject: COMMERCE
    domain_id: federal-analytics
    description: U.S. commerce and securities data
Campo Richiesto Default Descrizione
id Identificatore univoco
subject Uno dei valori subject sopra
domain_id Dominio a cui appartiene questa origine
description No "" Descrizione leggibile

Connettori personalizzati (REQ-1177)

I motori di federazione nativi — Postgres, DuckDB e ClickHouse — guadagnano raggiungibilità verso un nuovo tipo di origine quando un operatore dichiara un connettore per esso in config/custom_connectors.yaml. Non è richiesto codice. [tool-verified: provisa/federation/custom_connectors.py load_custom_connectors; provisa/federation/engine.py build_pg_engine, build_duckdb_engine, build_clickhouse_engine]

L'estensibilità dei connettori di per sé precede questo. Il motore Trino è da tempo estensibile al proprio livello — un connettore JDBC generico parametrizzato per tipo di origine, un corpo .properties di catalogo per tipo, e i plugin connettore Trino personalizzati propri di Provisa (Splunk, SharePoint, Calcite). [tool-verified: provisa/federation/trino_connectors.py _TrinoJdbcConnector, _TRINO_JDBC_TYPES; trino/plugins/trino-splunk, trino/plugins/trino-sharepoint, trino/plugins/trino-calcite] REQ-1177 porta la stessa estensibilità config-driven ai due motori nativi senza cluster, che in precedenza portavano un insieme fisso di connettori.

La configurazione viene fornita vuota. I connettori integrati coprono la raggiungibilità out-of-the-box; tutto in questo file è scritto dall'operatore. [tool-verified: config/custom_connectors.yaml line 52: connectors: []] Imposta PROVISA_CUSTOM_CONNECTORS per puntare a un percorso diverso (utile per i test).

Tipi di descrittore

Motore Tipo Meccanismo Cosa fornisce il descrittore
postgres pg_fdw SQL/MED (standard ISO) extension, server_options, user_mapping, supports_import, table_options, remote_schema
duckdb duckdb_attach INSTALL/LOAD + ATTACH extension, probe_symbol, attach_template, remote_schema
duckdb duckdb_scan INSTALL/LOAD + vista scanner extension, probe_symbol, scan_template
clickhouse clickhouse_database CREATE DATABASE ENGINE=… (espone automaticamente ogni tabella remota) ch_engine, engine_template
clickhouse clickhouse_table CREATE TABLE ENGINE=… per tabella (colonne dal registro) ch_engine, engine_template (può portare {table})
clickhouse clickhouse_scan CREATE TABLE ENGINE=…, ClickHouse inferisce lo schema ch_engine, engine_template

Postgres è generico. SQL/MED è uno standard ISO, quindi ogni FDW conforme condivide la stessa forma di DDL: CREATE SERVER … FOREIGN DATA WRAPPER <fdw> OPTIONS(…), opzionalmente CREATE USER MAPPING, poi o IMPORT FOREIGN SCHEMA (quando supports_import: true) oppure un CREATE FOREIGN TABLE esplicito per tabella (quando false). Un descrittore pg_fdw fornisce solo la variazione per-FDW — nome dell'estensione, chiavi delle opzioni server, chiavi di user-mapping, flag di import, opzioni tabella. Qualsiasi FDW conforme allo standard è quindi pilotabile solo da configurazione. [tool-verified: provisa/federation/custom_connectors.py GenericPgFdwConnector.details lines 98–125]

DuckDB supporta due meccanismi. Un'estensione che espone un catalogo via ATTACH usa duckdb_attach; una che espone una table-function di lettura usa duckdb_scan. Un'estensione che non rientra in nessuno dei due schemi non è supportata. [tool-verified: provisa/federation/custom_connectors.py GenericDuckDbAttachConnector, GenericDuckDbScanConnector]

ClickHouse supporta tre meccanismi, uno per ciascuna forma di motore di integrazione: un motore DATABASE relazionale che espone automaticamente ogni tabella remota (clickhouse_database, es. Redis/MySQL), un motore per tabella le cui colonne sono fornite dal registro (clickhouse_table, es. il bridge JDBC/ODBC — l'engine_template può portare un placeholder {table} che il runtime lega), e un motore file/lake/URL il cui schema ClickHouse inferisce (clickhouse_scan, es. HDFS/URL). SQLite (motore DATABASE, file, nessun server) e Hudi (lakehouse, zero-copy) sono forniti out-of-the-box. [tool-verified: provisa/federation/custom_connectors.py GenericClickHouseDatabaseConnector, GenericClickHouseTableConnector, GenericClickHouseScanConnector; provisa/federation/clickhouse_connectors.py ClickHouseSqliteConnector, ClickHouseHudiConnector] (REQ-1178)

Un valore kind sconosciuto fallisce in modo esplicito all'avvio — un errore di battitura nel descrittore non deve lasciare silenziosamente un tipo di origine irraggiungibile. [tool-verified: provisa/federation/custom_connectors.py load_custom_connectors lines 178–197]

Gating della sonda (probe)

La disponibilità viene verificata al momento dell'attach contro il catalogo di discovery standard di ciascun motore:

  • Postgres — controlla pg_extension, poi pg_available_extensions. [tool-verified: provisa/federation/connector_duckdb.py _probe_pg_extension lines 333–344]
  • DuckDB — esegue INSTALL/LOAD e controlla duckdb_functions() per il probe_symbol dichiarato. [tool-verified: provisa/federation/connector_duckdb.py _DuckDBExtensionConnector.probe lines 160–180]
  • ClickHouse — controlla system.table_engines per il ch_engine dichiarato; l'assenza dal build fallisce in modo esplicito. [tool-verified: provisa/federation/custom_connectors.py _probe_clickhouse_engine]

Un'estensione dichiarata che non è installabile fallisce in modo esplicito. Nessun salto silenzioso, nessun fallback. Un connettore la cui sonda fallisce semplicemente non è attivo per quel deployment.

Variabili di template

Ogni valore server_options, valore user_mapping, attach_template e scan_template può usare placeholder {field}. Campi disponibili: [tool-verified: provisa/federation/custom_connectors.py _source_fields lines 53–63]

{id}, {host}, {port}, {database}, {username}, {password}, {path}, {schema_name}, {table_name}, più qualsiasi chiave da federation_hints. I template attach di DuckDB ricevono anche {alias} — l'alias di catalogo interno che Provisa assegna al database attached.

Un template che referenzia un campo sconosciuto fallisce in modo esplicito al momento dell'attach, facendo emergere un mismatch descrittore/origine prima che DDL rotto raggiunga il motore.

Esempi

Postgres — MongoDB via mongo_fdw (nessun import di schema; colonne fornite per tabella)

# config/custom_connectors.yaml
connectors:
  - engine: postgres
    source_type: mongodb
    kind: pg_fdw
    extension: mongo_fdw
    mechanism: attach_r
    server_options:
      address: "{host}"
      port: "{port}"
    user_mapping:
      username: "{username}"
      password: "{password}"
    supports_import: false
    table_options:
      database: "{database}"
      collection: "{table_name}"

DuckDB — file Excel via read_xlsx (scan table-function)

  - engine: duckdb
    source_type: xlsx
    kind: duckdb_scan
    extension: excel
    install_from_community: false
    probe_symbol: read_xlsx
    scan_template: "read_xlsx('{path}')"

[tool-verified: config/custom_connectors.yaml commented examples, lines 26–50]

Con l'uno o l'altro descrittore in atto, registrare un'origine con il source_type dichiarato viene instradato attraverso il connettore personalizzato, soggetto a una sonda riuscita. Non è necessaria alcuna altra modifica di configurazione.


Warehouse come origini nominate

Snowflake, Databricks e ClickHouse possono essere registrati come origini nominate indipendentemente da quale motore di federazione è attivo. [tool-verified: executor/drivers/snowflake.py (REQ-988), executor/drivers/databricks.py (REQ-987), executor/drivers/clickhouse.py (REQ-986)]

Una volta registrato, Provisa legge il warehouse tramite il DirectDriver dell'origine e atterra una replica nello store di materializzazione del motore attivo. La query poi gira contro quella replica. Questo differisce dal percorso direct-capable tradizionale (asyncpg, aiomysql) dove il motore viene bypassato completamente — qui il motore esegue comunque la query, ma contro una replica locale piuttosto che sul wire verso il warehouse a ogni richiesta.

Le letture sono Arrow-native dove il warehouse lo supporta: Databricks usa Cloud Fetch, Snowflake usa fetch_arrow_table, e ClickHouse usa l'interfaccia HTTP columnar nativa.

I parametri di connessione estesi che i campi standard host/port/username/password non possono portare vanno in federation_hints:

sources:
  - id: my-databricks
    type: databricks
    host: my-workspace.azuredatabricks.net
    password: ${env:DATABRICKS_TOKEN}
    federation_hints:
      http_path: /sql/1.0/warehouses/xxxx   # required — the SQL Warehouse connection detail

  - id: my-snowflake
    type: snowflake
    host: org.snowflakecomputing.com
    username: svc_provisa
    password: ${env:SNOWFLAKE_PASSWORD}
    federation_hints:
      account: myorg-myaccount    # required — Snowflake account identifier
      warehouse: COMPUTE_WH       # optional — virtual warehouse to use
      role: PROVISA_ROLE          # optional — Snowflake role

  - id: my-clickhouse
    type: clickhouse
    host: ch.example.com
    port: 8123
    database: analytics
    username: default
    password: ${env:CLICKHOUSE_PASSWORD}
    federation_hints:
      secure: "true"              # optional — enables TLS on the HTTP interface

La registrazione come origine nominata è indipendente dalla selezione dello stesso warehouse come motore di federazione. Un'origine Snowflake su un motore DuckDB atterra una replica in DuckDB, non in Snowflake.

I dati cloud object/lake (file parquet, csv, iceberg, delta_lake su S3 / GCS / R2) sono un tipo di origine separato che si attacca in loco quando il motore attivo ha un connettore ATTACH per quel tipo. Nessuna replica viene atterrata — il motore esegue la scansione dell'object storage direttamente. Anche le credenziali per queste origini vanno in federation_hints:

sources:
  - id: r2-events
    type: parquet
    path: s3://my-bucket/events/2026/*.parquet
    federation_hints:
      access_key_id: ${env:R2_ACCESS_KEY}
      secret_access_key: ${env:R2_SECRET}
      account_id: ${env:R2_ACCOUNT_ID}     # Cloudflare R2 account (S3-compatible)

Campi di configurazione dell'origine

Tutte le origini condividono un insieme comune di campi. [tool-verified: provisa/core/models.py Source class, lines 138–204]

Campo Richiesto Default Descrizione
id Identificatore univoco; alfanumerico con trattini/underscore
type Tipo di origine (vedi tabelle sopra)
host No "" Hostname o IP
port No 0 Numero di porta
database No "" Nome del database
username No "" Nome utente
password No "" Password; usa ${env:VAR} per la risoluzione del secret
path No null Percorso file o URI cloud per origini basate su file e object/lake
base_url No null URL base per origini OpenAPI
pool_min No 1 Dimensione minima del connection pool (REQ-052)
pool_max No 5 Dimensione massima del connection pool (REQ-052)
use_pgbouncer No false Instrada le connessioni attraverso PgBouncer (REQ-053)
pgbouncer_port No 6432 Porta PgBouncer (REQ-053)
cache_enabled No true Abilita la cache delle risposte API
cache_ttl No null TTL della cache in secondi; eredita il default globale quando null
cache_catalog No null Catalogo federato per la cache API; di default il catalogo dell'origine stessa
cache_schema No api_cache Schema all'interno del catalogo di cache
naming_convention No null Sovrascrive la convenzione di naming globale per questa origine (REQ-194)
federation_hints No {} Proprietà di sessione passate al motore di federazione, e parametri di connessione estesi per origini warehouse (REQ-278, REQ-281)
mapping No {} Impostazioni di connettore specifiche per tipo per origini NoSQL e SaaS (es. auth_type di SharePoint, use_token di Splunk) (REQ-251)
allowed_domains No [] Restringe l'origine a domini specifici; vuoto = senza restrizioni
description No "" Descrizione leggibile

Origini Kafka

I topic Kafka vengono configurati separatamente sotto kafka_sources, indicizzati dall'id di origine di un'origine kafka registrata. [tool-verified: config/provisa.yaml lines 138–151] (REQ-147)

kafka_sources:

  - id: kafka-support
    topics:

      - id: tickets
        topic: support.tickets
        domain_id: sales-analytics
        description: "Inbound support tickets"
        default_window: 1h
        columns:

          - name: id
          - name: subject
          - name: status
          - name: created_at
Campo Descrizione
id Deve corrispondere all'id di un'origine con type: kafka
topics[].id Nome logico per questo topic all'interno di Provisa
topics[].topic Nome del topic Kafka
topics[].domain_id Dominio a cui appartiene questo topic
topics[].description Descrizione leggibile
topics[].default_window Finestra temporale di default per query con finestra (es. 1h) (REQ-148)
topics[].columns Definizioni di colonna per lo schema del topic (REQ-150)

Visibilità delle colonne

Il campo visible_to su ogni colonna è una lista di ID di ruolo che possono vedere quella colonna. [tool-verified: provisa/core/models.py Column class line 248; config/provisa.yaml lines 39–51]

columns:

  - name: email
    visible_to: [admin]        # only admin role sees this column

  - name: region
    visible_to: [admin, analyst]  # both roles see this column

Le colonne omesse dalla lista visible_to di un ruolo non appaiono nello schema GraphQL di quel ruolo e non possono essere interrogate o referenziate nei filtri (REQ-039).


Relazioni

Le relazioni collegano due tabelle registrate e appaiono come campi annidati in GraphQL. [tool-verified: provisa/core/models.py Relationship class lines 323–343; config/provisa.yaml lines 103–110] (REQ-019)

relationships:

  - id: orders-to-customers
    source_table_id: orders
    target_table_id: customers
    source_column: customer_id
    target_column: id
    cardinality: many-to-one
Campo Richiesto Descrizione
id Identificatore univoco per questa relazione
source_table_id Tabella che detiene la chiave esterna
target_table_id Tabella referenziata; vuoto per relazioni calcolate
source_column Colonna sulla tabella sorgente
target_column Colonna sulla tabella target; vuoto per relazioni calcolate
cardinality many-to-one o one-to-many (REQ-019)
materialize No Crea automaticamente una vista materializzata per join cross-source (REQ-158)
refresh_interval No Intervallo di refresh della MV in secondi (default: 300)
target_function_name No Nome della funzione DB per relazioni calcolate
function_arg No Quale argomento della funzione riceve il valore della colonna sorgente
alias No Tipo di relazione leggibile (es. WORKS_FOR)
graphql_alias No Nomina il campo SDL che questa relazione espone sul tipo padre. Quando assente, il nome viene derivato dal field_name della tabella target e dalla cardinalità della relazione. [tool-verified: provisa/compiler/schema_gen.py:1050]
disable_cypher No Quando true, esclude questa relazione dagli archi grafo Cypher
source_json_key No Estrae questa chiave dalla colonna sorgente come oggetto JSON prima del JOIN

Valori di cardinalità [tool-verified: provisa/core/models.py Cardinality enum, lines 79–81]:

  • many-to-one — ogni riga sorgente mappa a una riga target (FK verso PK)
  • one-to-many — ogni riga sorgente mappa a più righe target (inverso di sopra)

Regole di sicurezza a livello di riga

Le regole RLS iniettano clausole WHERE al momento della query, ambito a un ruolo e opzionalmente a una tabella o dominio. [tool-verified: provisa/core/models.py RLSRule class lines 391–395; config/provisa.yaml lines 128–131] (REQ-041)

rls_rules:

  - table_id: orders          # applies to orders table only
    role_id: analyst
    filter: "region = current_setting('provisa.user_region')"

  - domain_id: sales-analytics  # applies to every table in domain (REQ-402)
    role_id: analyst
    filter: "tenant_id = current_setting('provisa.tenant_id')"

Quando esistono sia una regola a livello di dominio che una a livello di tabella per lo stesso ruolo, la regola a livello di tabella ha la precedenza (REQ-403).

Campo Richiesto Descrizione
table_id Condizionale Tabella a cui applicare la regola; mutuamente esclusivo con domain_id
domain_id Condizionale Dominio a cui applicare la regola; si applica a tutte le tabelle nel dominio (REQ-402)
role_id Ruolo a cui si applica questa regola
filter Predicato SQL iniettato in WHERE; può referenziare variabili di sessione (REQ-041)

Funzioni e webhook

Funzioni DB

Traccia una funzione database ed esponila come query o mutation GraphQL. [tool-verified: provisa/core/models.py Function class lines 423–438; config/provisa.yaml lines 152–164] (REQ-205)

Le origini database possono anche scoprire automaticamente le loro stored procedure e funzioni dal catalogo del vendor (pg_proc, information_schema.routines, o equivalenti del vendor), eliminando la necessità di registrare ciascuna a mano. La discovery legge prokind e provolatile: le funzioni immutabili/stabili si registrano come relazioni parametrizzate (gli argomenti della procedura diventano parametri di query, la stessa forma delle tabelle OpenAPI GET), e le procedure volatili si registrano come mutation/funzioni tracciate. Le routine scoperte passano attraverso la governance Stage-2 in modo identico a quelle registrate a mano. [tool-verified: provisa/api/admin/introspect.py:541, provisa/api/admin/introspect.py:593] (REQ-887)

functions:

  - name: get_customers_by_region
    source_id: sales-pg
    schema: public
    function_name: get_customers_by_region
    returns: customers
    domain_id: sales-analytics
    description: "Returns customers filtered by region"
    visible_to: [admin, analyst]
    kind: query
    arguments:

      - name: p_region
        type: String
Campo Richiesto Default Descrizione
name Nome del campo GraphQL
source_id Origine contenente la funzione
schema No public Schema del database
function_name Nome effettivo della funzione database
returns ID della tabella registrata restituita dalla funzione (REQ-207)
arguments No [] Elenco di definizioni argomento {name, type} (REQ-211)
visible_to No [] Ruoli che possono chiamare questa funzione
writable_by No [] Ruoli che possono chiamarla come mutation
domain_id No "" Dominio a cui appartiene questa funzione
description No null Descrizione del campo GraphQL
kind No mutation "query" o "mutation" (REQ-205)

Webhook

Esponi un endpoint HTTP esterno come query o mutation GraphQL. [tool-verified: provisa/core/models.py Webhook class lines 441–455; config/provisa.yaml lines 166–178] (REQ-209)

webhooks:

  - name: notify_support
    url: http://localhost:9999/notify
    method: POST
    timeout_ms: 3000
    domain_id: sales-analytics
    description: "Send a support notification"
    visible_to: [admin]
    kind: mutation
    arguments:

      - name: message
        type: String
Campo Richiesto Default Descrizione
name Nome del campo GraphQL
url URL dell'endpoint webhook
method No POST Metodo HTTP
timeout_ms No 5000 Timeout della richiesta in millisecondi
returns No null ID della tabella registrata, o null per tipo inline
inline_return_type No [] Elenco di campi {name, type} per forme di ritorno personalizzate (REQ-210)
arguments No [] Elenco di definizioni argomento {name, type}
visible_to No [] Ruoli che possono chiamare questo webhook
domain_id No "" Dominio a cui appartiene questo webhook
description No null Descrizione del campo GraphQL
kind No mutation "query" o "mutation"

Autenticazione

L'autenticazione viene configurata sotto la chiave auth. [tool-verified: provisa/core/models.py AuthConfig class lines 467–477] (REQ-120)

Provider Descrizione
none Nessuna autenticazione; tutte le richieste trattate come il default_role
firebase Firebase Authentication; richiede project_id e service_account_key (REQ-121)
keycloak Keycloak OIDC (REQ-122)
oauth OAuth 2.0 generico (REQ-123)
simple Nome utente/password senza un provider esterno (REQ-124)
auth:
  provider: firebase
  assignments_source: provisa   # "claims" or "provisa"
  default_role: analyst
  default_assignments:

    - role_id: analyst
      domain_id: "*"
  firebase:
    project_id: ${env:FIREBASE_PROJECT_ID}
    service_account_key: ${env:FIREBASE_SERVICE_ACCOUNT_KEY}

assignments_source: claims legge le assegnazioni di ruolo dalle claim JWT. assignments_source: provisa le legge dallo store di assegnazioni proprio di Provisa. [tool-verified: provisa/core/models.py line 476] (REQ-551)


Routing di esecuzione

Esecuzione diretta — Le query a singola origine RDBMS vengono instradate al driver nativo per latenza sub-100ms (REQ-027). Le origini richiedono sia una voce SOURCE_TO_DIALECT che una voce SOURCE_TO_CONNECTOR per supportare questo percorso (REQ-229).

Esecuzione federata — Le query multi-source e le origini senza driver diretto vengono instradate attraverso il motore di federazione (REQ-028). Provisa include un motore di federazione integrato; punta al tuo cluster compatibile per deployment su larga scala (REQ-226).

Statistiche — Alla registrazione, Provisa esegue ANALYZE su ogni tabella pubblicata per innescare l'ottimizzatore cost-based (conteggio righe, frazione null, valori distinti, min/max). I fallimenti vengono loggati e non bloccano la registrazione (REQ-275).


Origini grafo e semantiche

Neo4j

Registra un database a grafo Neo4j come origine interrogabile. Gli steward scrivono query Cypher che proiettano valori scalari; Provisa mette in cache i risultati e li espone come tipi GraphQL (REQ-295).

Le query Cypher devono usare accessori di proprietà nella clausola RETURN (RETURN n.id AS id, n.name AS name) — restituire oggetti nodo viene rifiutato al momento della registrazione (REQ-296).

# Register via admin API (no YAML config required)
POST /admin/sources/neo4j
{
  "source_id": "graph",
  "host": "neo4j",
  "port": 7474,
  "database": "neo4j"
}

# Register a table (preview + validate before persisting)
POST /admin/sources/neo4j/graph/tables
{
  "table_name": "person_skills",
  "cypher": "MATCH (p:Person)-[:HAS_SKILL]->(s:Skill) RETURN p.name AS name, s.skill AS skill, p.experience AS years",
  "ttl": 300
}

L'endpoint di preview (POST /admin/sources/neo4j/{id}/preview) restituisce righe di esempio e blocca la registrazione se il Cypher restituisce oggetti nodo (REQ-296).

SPARQL

Registra qualsiasi triplestore conforme a SPARQL 1.1 (Apache Jena Fuseki, Virtuoso, Stardog, ecc.) come origine interrogabile (REQ-297).

Le query devono essere query SELECT. I nomi delle variabili nella clausola SELECT diventano automaticamente nomi di colonna (REQ-297).

# Register via admin API
POST /admin/sources/sparql
{
  "source_id": "knowledge-graph",
  "endpoint_url": "http://fuseki:3030/ds/sparql",
  "default_graph_uri": "http://example.org/graph"
}

# Register a table (executes LIMIT 5 probe to validate and infer columns)
POST /admin/sources/sparql/knowledge-graph/tables
{
  "table_name": "product_categories",
  "sparql_query": "SELECT ?product ?label ?category WHERE { ?product a :Product ; rdfs:label ?label ; :hasCategory ?category . }",
  "ttl": 600
}

Entrambi i connettori usano la pipeline di cache delle origini API — i risultati vengono memorizzati in PostgreSQL con TTL configurabile, rendendoli disponibili per JOIN federati cross-source (REQ-295, REQ-297, REQ-299).


Esempi di connessione

PostgreSQL

- id: sales-pg
  type: postgresql
  host: postgres
  port: 5432
  database: provisa
  username: provisa
  password: ${env:PG_PASSWORD}

Snowflake

- id: analytics-sf
  type: snowflake
  host: org.snowflakecomputing.com
  port: 443
  database: ANALYTICS
  username: svc_provisa
  password: ${env:SNOWFLAKE_PASSWORD}
  federation_hints:
    account: myorg-myaccount
    warehouse: COMPUTE_WH

Databricks

- id: lakehouse-db
  type: databricks
  host: my-workspace.azuredatabricks.net
  password: ${env:DATABRICKS_TOKEN}
  federation_hints:
    http_path: /sql/1.0/warehouses/xxxx

MongoDB

- id: reviews-mongo
  type: mongodb
  host: mongodb
  port: 27017
  database: provisa
  username: ""
  password: ""

Query cross-source

{
  orders(where: {region: {eq: "us"}}) {
    id
    amount
    customers {       # PostgreSQL
      name
      email
    }
    productReviews {  # MongoDB (federated)
      rating
      comment
    }
  }
}

Le porzioni a singola origine vengono instradate direttamente (REQ-027). I JOIN cross-source federano con coercizione di tipo automatica (REQ-028, REQ-552).