flAPI

Transforme templates SQL + YAML em APIs REST e ferramentas MCP — um binário estático com DuckDB embutido (Parquet, Postgres, BigQuery, S3 e mais de 50 fontes), RBAC por ferramenta e cache DuckLake.

Documentação

flAPI: APIs instantâneas baseadas em SQL

flAPI é um serviço poderoso que gera automaticamente APIs somente leitura para conjuntos de dados utilizando templates SQL. Construído sobre DuckDB e aproveitando seu mecanismo SQL e ecossistema de extensões, o flAPI oferece uma maneira integrada de conectar-se a várias fontes de dados e expô-las como APIs RESTful.

overview of flAPI

⚡ Recursos

  • Geração Automática de APIs: Crie APIs para seus conjuntos de dados sem codificação
  • Suporte a MCP (Model Context Protocol): Ferramentas de IA declarativas junto com endpoints REST, falando a revisão mais recente do MCP 2026-07-28 (era dupla: clientes modernos e legados) — com a extensão Tasks para consultas de longa duração, schemas tipados + resultados estruturados, descoberta OAuth, RBAC por ferramenta, shadow/dry-run, modelagem de resposta, limitação de taxa e um scanner de higiene contra injeção de prompt
  • Múltiplas Fontes de Dados: Conecte-se a BigQuery, SAP ERP & BW (via ERPL), Parquet, Iceberg, Postgres, MySQL e outros
  • Templates SQL: Sintaxe semelhante ao Mustache. Referências tipadas {{ params.X }} em campos int / double / boolean / date / time / uuid / enum / email / string são vinculadas como declarações preparadas do DuckDB — injeção de SQL é estruturalmente impossível nesses pontos
  • Cache: Cache com suporte a DuckLake com atualização completa e sincronização incremental
  • Segurança de produção: Hash de senha PBKDF2-SHA256, lista de permissões CORS orientada por configuração, limitação de taxa por usuário, log de auditoria de solicitações JSONL, terminação TLS, auditor de configuração de inicialização — tudo opcional via YAML de uma linha para que demos flapii project init permaneçam simples
  • Implantação fácil: Implante o flAPI com um único arquivo binário
  • Autopacote: Dobre toda a árvore de configuração do flapi (YAMLs + templates SQL + pequenos arquivos de dados) no próprio binário via flapi pack. scp flapi-prod user@host torna-se toda a implantação. Reproduzível (SOURCE_DATE_EPOCH), notarizável no macOS via um segmento Mach-O reservado, com uma lista de negação secreta (*.env, secrets/*, *.pem, *.key) aplicada no momento do empacotamento.
  • Telemetria que respeita a privacidade: Análises anônimas de inicialização/desligamento com fácil desativação via flag --no-telemetry, variável de ambiente FLAPI_NO_TELEMETRY ou flapi.yaml

📦 Instalação

A maneira mais rápida de experimentar o flAPI — sem download, sem Docker:

# Run the flapi server (note: "flapi" is taken on PyPI, so the package is "flapi-io")
uvx --from flapi-io flapi -c flapi.yaml

# Run the flapii CLI client (also bundled in flapi-io)
uvx --from flapi-io flapii

Ou instale permanentemente — um pacote fornece ambos os comandos:

pip install flapi-io   # installs both "flapi" and "flapii" commands

Binários pré-compilados e imagens Docker também estão disponíveis — veja abaixo.

🛠 Início Rápido

A maneira mais fácil de começar com o flAPI é usar a imagem Docker pré-construída.

1. Baixe a imagem Docker do Github Container Registry:

> docker pull ghcr.io/datazoode/flapi:latest

A imagem é bastante pequena e contém principalmente o binário flAPI que é estaticamente vinculado ao DuckDB v1.5.5. Detalhes sobre a imagem Docker podem ser encontrados no Dockerfile.

2. Execute o flAPI:

Depois de baixar o binário, você pode executar o flAPI executando o seguinte comando:

> docker run -it --rm -p 8080:8080 -p 8081:8081 -v $(pwd)/examples/:/config ghcr.io/datazoode/flapi -c /config/flapi.yaml

Os diferentes argumentos neste comando docker são:

  • -it --rm: Executa o contêiner em modo interativo e o remove após o processo terminar
  • -p 8080:8080: Expõe a porta 8080 do contêiner para o host, isso torna a API REST disponível em http://localhost:8080
  • -p 8081:8081: Expõe a porta 8081 para o servidor MCP (quando habilitado)
  • -v $(pwd)/examples/:/config: Monta o diretório local examples no diretório /config no contêiner, é onde o arquivo de configuração do flAPI deve ser encontrado.
  • ghcr.io/datazoode/flapi: A imagem docker a ser usada
  • -c /config/flapi.yaml: Este é um argumento para o aplicativo flAPI que informa para usar o arquivo flapi.yaml no diretório /config como arquivo de configuração.

2.1 Habilitar Suporte MCP:

Para habilitar o suporte MCP, você pode:

Opção A: Usar a flag de linha de comando

> docker run -it --rm -p 8080:8080 -p 8081:8081 -v $(pwd)/examples/:/config ghcr.io/datazoode/flapi -c /config/flapi.yaml --enable-mcp

Opção B: Configurar no flapi.yaml

mcp:
  enabled: true
  port: 8081
  # ... other MCP configuration

3.1 Testar o servidor de API:

Se tudo estiver configurado corretamente, você deve conseguir acessar a API na URL especificada no arquivo de configuração.

> curl 'http://localhost:8080/'

         ___
     ___( o)>   Welcome to
     \ <_. )    flAPI
      \`---'    

    Fast and Flexible API Framework
    powered by DuckDB

3.2 Obter uma visão geral dos endpoints disponíveis:

O servidor flAPI cria uma interface Swagger UI incorporada que fornece uma visão geral dos endpoints disponíveis e permite testá-los. Ela pode ser encontrada em

> http://localhost:8080/doc

Você deve ver a página familiar do Swagger UI:

flAPI Swagger UI

O yaml bruto Swagger 2.0 também está disponível em http://localhost:8080/doc.yaml

3.3 Testar o servidor MCP:

Se o MCP estiver habilitado, você também pode testar o servidor MCP:

# Check MCP server health
> curl 'http://localhost:8081/mcp/health'

{"status":"healthy","server":"flapi-mcp-server","version":"0.3.0","protocol_version":"2024-11-05","tools_count":0}

# Initialize MCP connection
> curl -X POST http://localhost:8081/mcp/jsonrpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "initialize"}'

# List available tools
> curl -X POST http://localhost:8081/mcp/jsonrpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'

🤖 Suporte a MCP (Model Context Protocol)

O flAPI agora suporta o Model Context Protocol (MCP) em uma abordagem de configuração unificada. Cada instância do flAPI executa automaticamente tanto um servidor de API REST quanto um servidor MCP simultaneamente, permitindo que você crie ferramentas de IA junto com seus endpoints REST usando os mesmos arquivos de configuração e templates SQL.

Recursos Principais

  • MCP 2026-07-28 (era dupla): atende a revisão MCP stateless mais recente (server/discover, metadados por solicitação, resultados armazenáveis em cache, descoberta OAuth via RFC 9728) juntamente com o protocolo legado initialize /session — clientes existentes continuam funcionando sem alterações
  • Ferramentas de longa duração (extensão Tasks): marque uma ferramenta async e consultas lentas retornam um identificador de tarefa imediatamente em vez de bloquear a conexão; o armazenamento durável de tarefas sobrevive a uma reinicialização, com tasks/get / tasks/cancel e isolamento por chamador
  • Contratos de ferramentas tipados e estruturados: parâmetros de ferramenta anunciam tipos e restrições reais (intervalos int, datas, uuid, enum, …), resultados carregam structuredContent legível por máquina, um outputSchema é aprendido após o primeiro uso, e falhas retornam resultados isError acionáveis dos quais o modelo pode se autocorrigir
  • Configuração Unificada: Arquivos YAML únicos podem definir endpoints REST, ferramentas MCP e recursos MCP
  • Detecção Automática: O tipo de configuração é determinado pela presença de url-path (REST), mcp-tool (ferramenta MCP) ou mcp-resource (recurso MCP)
  • Componentes Compartilhados: Ferramentas e recursos MCP usam os mesmos templates SQL, validação de parâmetros, autenticação e cache que os endpoints REST
  • Integração de Segurança: autorização de método aplicada em cada solicitação, RBAC por ferramenta/recurso/prompt (allowed-roles), shadow/dry-run (_dryRun), modelagem de resposta, limitação de taxa por ferramenta e um scanner de higiene de descrição de ferramenta
  • Descoberta de Ferramentas: descoberta automática de ferramentas, paginação, templates de recursos (flapi://customers/{id}) e x-mcp-header para roteamento de borda por locatário

Consulte docs/MCP_REFERENCE.md — o modelo de era dupla e todos os novos recursos estão documentados na §11.

Endpoints MCP

  • POST /mcp/jsonrpc - Endpoint JSON-RPC principal para chamadas de ferramentas
  • GET /mcp/health - Endpoint de verificação de saúde

Configuração Unificada

O MCP agora está habilitado automaticamente - nenhuma configuração separada é necessária! Cada instância do flAPI executa servidores REST API e MCP simultaneamente.

Arquivos de configuração podem definir múltiplos tipos de entidades:

Endpoint REST + Ferramenta MCP (Unificado)

# Single configuration file serves as BOTH REST endpoint AND MCP tool
url-path: /customers/                    # Makes this a REST endpoint
mcp-tool:                                # Also makes this an MCP tool
  name: get_customers
  description: Retrieve customer information by ID
  result-mime-type: application/json

request:
  - field-name: id
    field-in: query
    description: Customer ID
    required: false
    validators:
      - type: int
        min: 1
        max: 1000000
        preventSqlInjection: true

template-source: customers.sql
connection: [customers-parquet]

rate-limit:
  enabled: true
  max: 100
  interval: 60

auth:
  enabled: true
  type: basic
  users:
    - username: admin
      password: secret
      roles: [admin]

Somente Recurso MCP

# MCP Resource example
mcp-resource:
  name: customer_schema
  description: Customer database schema definition
  mime-type: application/json

template-source: customer-schema.sql
connection: [customers-parquet]

Usando Ferramentas MCP

Uma vez que o MCP está habilitado, você pode interagir com ferramentas usando JSON-RPC 2.0:

# Check MCP server health
curl 'http://localhost:8081/mcp/health'

# Initialize MCP connection
curl -X POST http://localhost:8081/mcp/jsonrpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "initialize"}'

# List available tools (discovered from unified configuration)
curl -X POST http://localhost:8081/mcp/jsonrpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'

# Call a tool (same SQL template used for both REST and MCP)
curl -X POST http://localhost:8081/mcp/jsonrpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "get_customers", "arguments": {"id": "123"}}}'

🎓 Exemplo

Aqui está um exemplo simples de como criar um endpoint de API usando o flAPI:

1. Crie uma configuração básica do flAPI

O flAPI usa o popular formato YAML para configurar os endpoints da API. Um arquivo de configuração básico se parece com isto:

project_name: example-flapi-project
project_description: An example flAPI project demonstrating various configuration options
template:
  path: './sqls'            # The path where SQL templates and API endpoint configurations are stored
  environment-whitelist:    # Optional: List of regular expressions for whitelisting envvars which are available in the templates
    - '^FLAPI_.*'

duckdb:                     # Configuration of the DuckDB embedded into flAPI
  db_path: ./flapi_cache.db # Optional: remove or comment out for in-memory database, we use this store also as cache
  access_mode: READ_WRITE   # See the https://duckdb.org/docs/configuration/overview) for more details
  threads: 8
  max_memory: 8GB
  default_order: DESC

connections:                # A YAML map of database connection configurations, a API endpoint needs to reference one of these connections
   bigquery-lakehouse: 
                            # SQL commands to initialize the connection (e.g., e.g. installing, loading and configuring the BQ a DuckDB extension)
      init: |
         INSTALL 'bigquery' FROM 'http://storage.googleapis.com/hafenkran';
         LOAD 'bigquery';
      properties:           # A YAML map of connection-specific properties (accessible in templates via {{ context.conn.property_name }})
         project_id: 'my-project-id'

   customers-parquet: 
      properties:
         path: './data/customers.parquet'

heartbeat:
  enabled: true            # The eartbeat worker is a background thread which can can be used to periodically trigger endpionts
  worker-interval: 10      # The interval in seconds at which the heartbeat worker will trigger endpoints

enforce-https:
  enabled: false           # Whether to force HTTPS for the API connections, we strongly recommend to use a reverse proxy to do SSL termination
  # ssl-cert-file: './ssl/cert.pem'
  # ssl-key-file: './ssl/key.pem'

Depois disso, garanta que o caminho do template (./sqls neste exemplo) exista.

1. Defina seu endpoint de API (./sqls/customers.yaml):

Cada endpoint é definido pelo menos por um arquivo YAML e um template SQL correspondente no caminho do template. Para nosso exemplo, criaremos o arquivo ./sqls/customers.yaml:

url-path: /customers/      # The URL path at which the endpoint will be available

request:                  # The request configuration for the endpoint, this defines the parameters that can be used in the query
  - field-name: id
    field-in: query       # The location of the parameter, other options are 'path', 'query' and 'body'
    description: Customer ID # A description of the parameter, this is used in the auto-generated API documentation
    required: false       # Whether the parameter is required
    validators:           # A list of validators that will be applied to the parameter
      - type: int
        min: 1
        max: 1000000
        preventSqlInjection: true

template-source: customers.sql # The path to the SQL template that will be used to generate the endpoint
connection: 
  - customers-parquet          # The connection that will be used to execute the query

rate-limit:
  enabled: true           # Whether rate limiting is enabled for the endpoint
  max: 100                # The maximum number of requests per interval
  interval: 60            # The interval in seconds
  
auth:
  enabled: true           # Whether authentication is enabled for the endpoint
  type: basic             # The type of authentication, other options are 'basic' and 'bearer'
  users:                  # The users that are allowed to access the endpoint
    - username: admin
      password: secret
      roles: [admin]
    - username: user
      password: password
      roles: [read]

heartbeat:
  enabled: true           # Whether the heartbeat worker if enabled will trigger the endpoint periodically
  params:                 # A YAML map of parameters that will be passed by the heartbeat worker to the endpoint
    id: 123

Existem muito mais opções de configuração disponíveis, consulte a documentação completa para mais detalhes.

2. Configure o template SQL do endpoint (./sqls/customers.sql):

Após a criação da configuração YAML do endpoint, precisamos conectar o template SQL que conecta o endpoint à conexão de dados. Os arquivos de template usam a linguagem de template Mustache para gerar dinamicamente a consulta SQL.

SELECT * FROM '{{{conn.path}}}'
WHERE 1=1
{{#params.id}}
  AND c_custkey = {{{ params.id }}}
{{/params.id}}

O template acima usa o parâmetro path definido na configuração da conexão para consultar diretamente um arquivo parquet local. Se o parâmetro id for fornecido, ele será usado para filtrar os resultados.

3. Envie uma solicitação:

Para testar o endpoint e ver se tudo funcionou, podemos usar curl. Também devemos fornecer as credenciais corretas de autenticação básica (admin:secret neste caso). Para facilitar a leitura do resultado JSON, canalizamos a saída para jq.

> curl -X GET -u admin:secret "http://localhost:8080/customers?id=123" | jq .

{
  "next": "",
  "total_count": 1,
  "data": [
    {
      "c_mktsegment": "BUILDING",
      "c_acctbal": 5897.82999999999992724,
      "c_phone": "15-817-151-1168",
      "c_address": "YsOnaaER8MkvK5cpf4VSlq",
      "c_nationkey": 5,
      "c_name": "Customer#000000123",
      "c_comment": "ependencies. regular, ironic requests are fluffily regu",
      "c_custkey": 123
    }
  ]
}

⁉️ Cache com suporte a DuckLake (implementação atual)

O flAPI usa a extensão DuckDB DuckLake para fornecer cache moderno baseado em snapshots. Você escreve o SQL para definir a tabela em cache, e o flAPI gerencia schemas, snapshots, retenção, agendamento e logs de auditoria.

Início rápido: Cache de atualização completa

  1. Configure o DuckLake globalmente (o alias é cache por padrão):
ducklake:
  enabled: true
  alias: cache
  metadata-path: ./examples/data/cache.ducklake
  data-path: ./examples/data/cache.ducklake
  data-inlining-row-limit: 10  # Enable data inlining for small changes (optional)
  retention:
    max-snapshot-age: 14d
  compaction:
    enabled: false
  scheduler:
    enabled: true
  1. Adicione o bloco de cache ao seu endpoint (sem primary-key / cursor → atualização completa):
url-path: /publicis
template-source: publicis.sql
connection: [bigquery-lakehouse]

cache:
  enabled: true
  table: publicis_cache
  schema: analytics
  schedule: 5m
  retention:
    max_snapshot_age: 14d
  template_file: publicis/publicis_cache.sql
  1. Escreva o template SQL do cache (CTAS):
-- publicis/publicis_cache.sql
CREATE OR REPLACE TABLE {{cache.catalog}}.{{cache.schema}}.{{cache.table}} AS
SELECT
  p.country,
  p.product_category,
  p.campaign_type,
  p.channel,
  sum(p.clicks) AS clicks
FROM bigquery_scan('{{{conn.project_id}}}.landing__publicis.kaercher_union_all') AS p
GROUP BY 1, 2, 3, 4;
  1. Consulte a partir do cache em seu SQL principal:
-- publicis.sql
SELECT
  p.country,
  p.product_category,
  p.campaign_type,
  p.channel,
  p.clicks
FROM {{cache.catalog}}.{{cache.schema}}.{{cache.table}} AS p
WHERE 1=1

Observações:

  • O schema do cache (cache.analytics) é criado automaticamente se estiver ausente.
  • Solicitações GET regulares nunca atualizam o cache. As atualizações ocorrem no aquecimento, no agendamento ou via API manual.
  • Inlining de Dados: Quando data-inlining-row-limit está configurado, pequenas alterações no cache (≤ limite de linhas especificado) são escritas diretamente nos metadados do DuckLake em vez de criar arquivos Parquet separados. Isso melhora o desempenho para pequenas atualizações incrementais.

Inlining de dados (opcional, para pequenas alterações)

O DuckLake suporta escrever inserções muito pequenas diretamente no catálogo de metadados em vez de criar um arquivo Parquet para cada micro-lote. Isso é chamado de "Data Inlining" e pode acelerar significativamente atualizações pequenas e frequentes.

  • Habilitar globalmente: configure uma vez sob o bloco de nível superior ducklake:
    ducklake:
      enabled: true
      alias: cache
      metadata_path: ./examples/data/cache.ducklake
      data_path: ./examples/data/cache.ducklake
      data_inlining_row_limit: 10  # inline inserts up to 10 rows
    
  • Comportamento:
    • Inserções com linhas ≤ data-inlining-row-limit são incorporadas nos metadados do catálogo.
      • Inserções maiores automaticamente voltam para gravações normais de arquivos Parquet.
      • O inlining se aplica a todos os caches (configuração global), sem alternância por endpoint.
  • Liberação manual (opcional): você pode liberar dados incorporados para arquivos Parquet a qualquer momento usando a função do DuckLake. Supondo que seu alias DuckLake seja cache:
    -- Flush all inlined data in the catalog
    CALL ducklake_flush_inlined_data('cache');
    -- Flush only a specific schema
    CALL ducklake_flush_inlined_data('cache', schema_name => 'analytics');
    -- Flush only a specific table (default schema "main")
    CALL ducklake_flush_inlined_data('cache', table_name => 'events_cache');
    -- Flush a specific table in a specific schema
    CALL ducklake_flush_inlined_data('cache', schema_name => 'analytics', table_name => 'events_cache');
    
  • Observações:
    • Este recurso é fornecido pelo DuckLake e atualmente está marcado como experimental upstream. Consulte a documentação do DuckLake para detalhes: Data Inlining.
      • Se você não definir data_inlining_row_limit, o flAPI não habilitará o inlining e o DuckLake usará gravações Parquet regulares.

Avançado: Anexação incremental e mesclagem

O mecanismo infere o modo de sincronização do seu YAML:

  • Sem primary-key, sem cursor → atualização completa (CTAS)
  • Com cursor apenas → anexação incremental
  • Com primary-key + cursor → mesclagem incremental (upsert)

Exemplos de YAMLs:

# Incremental append
cache:
  enabled: true
  table: events_cache
  schema: analytics
  schedule: 10m
  cursor:
    column: created_at
    type: timestamp
  template-file: events/events_cache.sql

# Incremental merge (upsert)
cache:
  enabled: true
  table: customers_cache
  schema: analytics
  schedule: 15m
  primary-key: [id]
  cursor:
    column: updated_at
    type: timestamp
  template_file: customers/customers_cache.sql

Variáveis de template de cache disponíveis para seu SQL:

  • {{cache.catalog}}, {{cache.schema}}, {{cache.table}}, {{cache.schedule}}
  • {{cache.snapshotId}}, {{cache.snapshotTimestamp}} (atual)
  • {{cache.previousSnapshotId}}, {{cache.previousSnapshotTimestamp}} (anterior)
  • {{cache.cursorColumn}}, {{cache.cursorType}}
  • {{cache.primaryKeys}}
  • {{params.cacheMode}} está disponível com os valores full, append ou merge

Exemplo de acréscimo incremental:

-- events/events_cache.sql
INSERT INTO {{cache.catalog}}.{{cache.schema}}.{{cache.table}}
SELECT *
FROM source_events
WHERE {{#cache.previousSnapshotTimestamp}} event_time > TIMESTAMP '{{cache.previousSnapshotTimestamp}}' {{/cache.previousSnapshotTimestamp}}

Exemplo de mesclagem incremental:

-- customers/customers_cache.sql
MERGE INTO {{cache.catalog}}.{{cache.schema}}.{{cache.table}} AS t
USING (
  SELECT * FROM source_customers
  WHERE {{#cache.previousSnapshotTimestamp}} updated_at > TIMESTAMP '{{cache.previousSnapshotTimestamp}}' {{/cache.previousSnapshotTimestamp}}
) AS s
ON t.id = s.id
WHEN MATCHED THEN UPDATE SET
  name = s.name,
  email = s.email,
  updated_at = s.updated_at
WHEN NOT MATCHED THEN INSERT (*) VALUES (s.*);

Quando o cache é atualizado?

  • Aquecimento na inicialização: o flAPI atualiza os caches para endpoints com cache habilitado.
  • Atualização agendada: controlada por cache.schedule em cada endpoint (por exemplo, 5m).
  • Atualização manual: chame a API de atualização (veja abaixo).
  • Requisições GET regulares não atualizam o cache.

Auditoria, retenção, compactação e APIs de controle

O flAPI mantém uma tabela de auditoria dentro do DuckLake em cache.audit.sync_events e fornece endpoints de controle:

  • Atualização manual:
curl -X POST "http://localhost:8080/api/v1/_config/endpoints/publicis/cache/refresh"
  • Logs de auditoria (específicos de endpoint e globais):
curl "http://localhost:8080/api/v1/_config/endpoints/publicis/cache/audit"
curl "http://localhost:8080/api/v1/_config/cache/audit"
  • Coleta de lixo (retenção): a retenção pode ser configurada por endpoint em cache.retention:
cache:
  retention:
    max-snapshot-age: 7d     # time-based retention
    # keep-last-snapshots: 3 # version-based retention (subject to DuckLake support)

O sistema aplica a retenção após cada atualização e você também pode acionar a coleta de lixo manualmente:

curl -X POST "http://localhost:8080/api/v1/_config/endpoints/publicis/cache/gc"
  • Compactação: se habilitada no ducklake.scheduler global, a mesclagem periódica de arquivos é executada via ducklake_merge_adjacent_files do DuckLake.

Guia de autoria de modelos (referência)

Use estas variáveis dentro dos seus modelos de cache e consultas principais:

  • Identificação
    • {{cache.catalog}} → geralmente cache
      • {{cache.schema}} → por exemplo, analytics (criado automaticamente se ausente)
      • {{cache.table}} → o nome da sua tabela de cache
  • Modo e agendamento
    • {{params.cacheMode}}full | append | merge
      • {{cache.schedule}} → se definido no YAML
  • Instantâneos
    • {{cache.snapshotId}}, {{cache.snapshotTimestamp}}
      • {{cache.previousSnapshotId}}, {{cache.previousSnapshotTimestamp}}
  • Dicas incrementais
    • {{cache.cursorColumn}}, {{cache.cursorType}}
      • {{cache.primaryKeys}} → lista separada por vírgulas, por exemplo, id,tenant_id

Dicas de autoria:

  • Atualização completa: use CREATE OR REPLACE TABLE ... AS SELECT ....
  • Acréscimo: INSERT INTO cache.table SELECT ... WHERE event_time > previousSnapshotTimestamp.
  • Mesclagem: MERGE INTO cache.table USING (SELECT ...) ON pk ....
  • Não crie esquemas nos modelos; o flAPI faz isso automaticamente.

Solução de problemas

  • A atualização do cache acontece a cada requisição: por design, isso está desabilitado. Certifique-se de não estar chamando o endpoint de atualização manual a partir de um cliente e de que seus logs mostram apenas atualizações agendadas ou de aquecimento.
  • Esquema não encontrado: verifique se cache.schema está definido; o flAPI o criará automaticamente.
  • Erros de retenção: use max-snapshot-age baseado em tempo primeiro. A retenção baseada em versão depende do suporte do DuckLake.

🧩 Inclusões YAML e variáveis de ambiente

O flAPI estende o YAML simples com recursos leves de inclusão e variáveis de ambiente para que você possa manter as configurações modulares e cientes do ambiente.

Variáveis de ambiente

  • Escreva variáveis de ambiente como {{env.VAR_NAME}} em qualquer lugar do seu YAML.
  • Somente variáveis que correspondem à lista de permissões na sua configuração raiz são substituídas:
    template:
      path: './sqls'
      environment-whitelist:
        - '^FLAPI_.*'     # allow all variables starting with FLAPI_
        - '^PROJECT_.*'   # optional additional prefixes
    
  • Se a lista de permissões estiver vazia ou omitida, todas as variáveis de ambiente são permitidas.

Exemplos:

# Substitute inside strings
project-name: "${{env.PROJECT_NAME}}"

# Build include paths dynamically
template:
  path: "{{env.CONFIG_DIR}}/sqls"

Sintaxe de inclusão

Você pode inserir conteúdo de outro arquivo YAML diretamente no documento atual.

  • Inclusão básica: {{include from path/to/file.yaml}}
  • Inclusão de seção: {{include:top_level_key from path/to/file.yaml}} inclui apenas essa chave
  • Inclusão condicional: acrescente if <condition> a qualquer uma das formas

Condições suportadas:

  • true ou false
  • env.VAR_NAME (incluir se a variável existir e não estiver vazia)
  • !env.VAR_NAME (incluir se a variável estiver ausente ou vazia)

Exemplos:

# Include another YAML file relative to this file
{{include from common/settings.yaml}}

# Include only a section (top-level key) from a file
{{include:connections from shared/connections.yaml}}

# Conditional include based on an environment variable
{{include from overrides/dev.yaml if env.FLAPI_ENV}}

# Use env var in the include path
{{include from {{env.CONFIG_DIR}}/secrets.yaml}}

Regras de resolução e comportamento:

  • Os caminhos são resolvidos relativos ao arquivo atual primeiro; caminhos absolutos são suportados.
  • Inclusões dentro de comentários YAML são ignoradas (por exemplo, linhas que começam com #).
  • As inclusões são expandidas antes de o YAML ser analisado.
  • As inclusões não são recursivas: diretivas de inclusão dentro de arquivos incluídos não são processadas posteriormente.
  • Inclusões circulares são protegidas dentro de uma única passagem de expansão; evite ciclos.

Dicas:

  • Prefira inclusões de seção ({{include:...}}) para evitar sobrescrever acidentalmente chaves não relacionadas.
  • Mantenha blocos compartilhados em arquivos pequenos (por exemplo, connections.yaml, auth.yaml) e inclua-os onde necessário.

📦 Autopacote (implantação de binário único)

O mesmo binário flapi que serve a API pode dobrar uma árvore de configuração inteira em si mesmo, produzindo um executável autocontido implantável via scp.

# Pack a config tree into a new bundled binary
flapi pack --in ./examples --out flapi-prod

# Inspect what's bundled
./flapi-prod info

# Extract the bundle for debugging
./flapi-prod unpack --to /tmp/extracted

# Run it — serves the bundled config from any cwd
cd /tmp && ./flapi-prod

Como funciona: um arquivo ZIP é anexado após o executável no Linux/Windows (ou gravado em um segmento Mach-O __FLAPI/__bundle pré-alocado no macOS, e depois re- codesign -ed para que o resultado seja notarizável). Na inicialização, o flAPI faz uma varredura reversa em busca do pacote (ou sonda o segmento no macOS) e registra um EmbeddedArchiveFileProvider além de um sistema de arquivos DuckDB embed:// para que configuração / modelos SQL / chamadas read_csv() sejam resolvidos para o pacote em memória. Se nenhum pacote estiver presente (binário não empacotado, cauda truncada), todos os caminhos voltam ao sistema de arquivos local sem alterações — operadores existentes não veem mudança de comportamento.

Segredos ficam fora do pacote. flapi pack recusa arquivos que correspondem a *.env, secrets/*, *.pem, *.key por padrão. A substituição (--allow-secrets) é apenas para testes. As credenciais vêm do ambiente em tempo de execução (interpolação YAML AWS_*, GOOGLE_*, AZURE_*, FLAPI_CONFIG_SERVICE_TOKEN, {{env.VAR}}).

Builds reproduzíveis. Defina SOURCE_DATE_EPOCH antes de flapi pack e a saída será byte idêntica entre execuções:

SOURCE_DATE_EPOCH=1700000000 flapi pack --in examples --out a
SOURCE_DATE_EPOCH=1700000000 flapi pack --in examples --out b
sha256sum a b   # identical

Variáveis de ambiente 12-factor. FLAPI_CONFIG faz fallback para -c / --config; FLAPI_LOG_LEVEL faz fallback para --log-level. O flag da CLI vence a variável de ambiente, que vence o padrão embutido. Níveis de log inválidos saem com código diferente de zero e uma mensagem de erro de uma linha.

Notas para macOS. O tamanho do segmento reservado é de 16 MiB por padrão (botão FLAPI_RESERVED_BUNDLE_MIB no momento da configuração do CMake); pacotes superdimensionados saem com código diferente de zero e um erro corretivo. Um flag --macos-append está disponível para depuração local — ele usa o layout de anexação após EOF do Linux/Windows, mas o resultado é intencionalmente não notarizável.

Consulte docs/CLI_REFERENCE.md §3 e docs/spec/DESIGN_DECISIONS.md §9 para referência completa e justificativa.

🏭 Compilando a partir do código-fonte

O código-fonte do flAPI é escrito em C++ e se assemelha muito ao processo de build do DuckDB. Uma boa documentação do processo de build é a ação do GitHub em build.yaml. Em essência, alguns pré-requisitos precisam ser atendidos: Em essência, alguns pré-requisitos precisam ser atendidos:

  • Instale as dependências: sudo apt-get install -y build-essential cmake ninja-build
  • Faça o checkout do repositório e submódulos: git clone --recurse-submodules https://github.com/datazoode/flapi.git
  • Compile o projeto: make release

O processo de build baixará e compilará o DuckDB v1.1.2 e instalará o gerenciador de pacotes vcpkg. Dependemos dos seguintes ports do vcpkg:

  • argparse - Analisador de argumentos de linha de comando
  • crow - Nosso framework REST-Web e manipulação de JSON
  • yaml-cpp - Analisador YAML
  • jwt-cpp - Biblioteca de JSON Web Token
  • openssl - Biblioteca de criptografia
  • catch2 - Framework de testes

Nota: O suporte a MCP é embutido e não requer dependências adicionais além do que já está incluído.

📚 Documentação

Para informações mais detalhadas, consulte nossa documentação completa:

Registro MCP

O flAPI está listado no Registro MCP oficial sob o nome abaixo (esta linha também serve como marcador de propriedade PyPI do registro):

mcp-name: io.github.datazoode/flapi

📊 Telemetria

O flAPI envia eventos anônimos de application_start e application_stop para ajudar a equipe a entender a adoção. Nenhum dado de consulta, credencial ou informação pessoal é enviado.

Desativar (qualquer uma destas opções é suficiente):

# One-off via CLI flag
./flapi --no-telemetry

# Per-session via environment variable
export FLAPI_NO_TELEMETRY=1
./flapi

# Permanently via config file (flapi.yaml)
telemetry:
  enabled: false

Consulte a Referência da CLI e a Referência de Configuração para detalhes completos.

🤝 Contribuindo

Aceitamos contribuições! Consulte nosso Guia de Contribuição para mais detalhes.

📄 Licença

O flAPI é licenciado sob a Business Source License (BSL) Versão 1.1. A BSL é uma licença de código-fonte disponível que concede as seguintes permissões:

Permitido

  1. Copiar, modificar e criar obras derivadas: Você pode copiar o software, modificá-lo e criar obras derivadas.
  2. Redistribuir e uso não produtivo: A redistribuição e o uso não produtivo do software são permitidos.
  3. Uso produtivo limitado: Você pode usar o flAPI em produção, mas com uma restrição (veja abaixo).
  4. Direitos de mudança de licença: Após a Data de Mudança (cinco anos a partir da primeira publicação da Obra Licenciada), o software se torna automaticamente disponível sob a Licença de Mudança (MPL 2.0).

Não permitido

  1. Oferecimento a terceiros em base hospedada ou embutida: A Concessão de Uso Adicional restringe explicitamente o uso do software de forma que o ofereça a terceiros como serviço hospedado ou componente embutido. Se você quiser fazer isso, precisa de uma licença comercial.
  2. Violação dos requisitos atuais da licença: Se o seu uso não estiver em conformidade com a BSL, você deve comprar uma licença comercial ou parar de usar o flAPI.
  3. Uso de marcas registradas: Você não tem direitos sobre as marcas registradas ou logotipos do flAPI ou DataZoo, exceto conforme expressamente exigido pela Licença.

Para licenciamento comercial — embutir o flAPI em um produto, oferecê-lo como serviço hospedado ou qualquer redistribuição que a Concessão de Uso Adicional restrinja — entre em contato com contact@data-zoo.de.

Parâmetros de licenciamento

  • Licenciante: DataZoo GmbH
  • Obra Licenciada: flAPI — framework SQL-para-API
  • Data de Mudança: cinco anos a partir da primeira publicação de cada versão
  • Licença de Mudança: MPL 2.0

Consulte o arquivo LICENSE para o texto completo.

🙋♀️ Suporte

Se você tiver dúvidas ou precisar de ajuda, abra um problema ou participe do nosso chat da comunidade.


Feedback

Se o flAPI se comportar mal — um endpoint que não serve, um cache que não invalida, um fluxo de autenticação que não conclui — abra um problema. As implantações diferem de maneiras que não podemos reproduzir aqui, então um relatório com sua configuração é o caminho mais rápido para uma correção. Cada resposta de erro JSON carrega um link report_issue exatamente por esse motivo.

Se economizou seu tempo, uma estrela no repositório ajuda outras pessoas a encontrá-lo.

Em uma inicialização interativa, um pequeno banner diz o mesmo uma vez por dia. Sob um contêiner ou systemd não há terminal, então ele nunca imprime — a linha de log de inicialização carrega o ponteiro. Silencie ambos com DATAZOO_NO_BANNER=1.