From 487413aaf723be6bff825c3c32836bd88bb0af66 Mon Sep 17 00:00:00 2001 From: "Komesu, D.K." Date: Sun, 17 May 2026 22:24:25 -0300 Subject: [PATCH] docs: documentar quantilica-cloud e quantilica-catalog; atualizar changelog e status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adicionar página completa para quantilica-cloud (plugin CLI de sync de manifestos) - Adicionar página completa para quantilica-catalog (modelo canônico de observações) - Incluir ambos na nav do mkdocs.yml e na tabela de fundações/index.md - Corrigir repo_url de /Quantilica para /Quantilica/docs - Corrigir endereço docs.quantilica.io → docs.quantilica.com no README - Atualizar changelog com lançamentos de cloud, catalog, integração quantilica-io - Atualizar datas de verificação do status.md para 2026-05-17 Co-Authored-By: Claude Sonnet 4.6 --- README.md | 4 +- docs/changelog.md | 7 ++ docs/fundacoes/index.md | 24 ++++ docs/fundacoes/quantilica-catalog.md | 181 +++++++++++++++++++++++++++ docs/fundacoes/quantilica-cloud.md | 112 +++++++++++++++++ docs/index.md | 2 + docs/status.md | 18 +-- mkdocs.yml | 4 +- 8 files changed, 340 insertions(+), 12 deletions(-) create mode 100644 docs/fundacoes/quantilica-catalog.md create mode 100644 docs/fundacoes/quantilica-cloud.md diff --git a/README.md b/README.md index 5716bba..48282f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Quantilica — Documentação -Portal público da Quantilica (`docs.quantilica.io`), construído com [MkDocs Material](https://squidfunk.github.io/mkdocs-material/). +Portal público da Quantilica (`docs.quantilica.com`), construído com [MkDocs Material](https://squidfunk.github.io/mkdocs-material/). ## Desenvolvimento local @@ -9,7 +9,7 @@ uv sync uv run mkdocs serve ``` -Site disponível em `http://127.0.0.1:8000`. +Site disponível em `https://docs.quantilica.com/`. ## Estrutura diff --git a/docs/changelog.md b/docs/changelog.md index 5bcca0d..57ee860 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,6 +7,13 @@ description: Marcos importantes do ecossistema Quantilica — novos pacotes, mud Marcos importantes do ecossistema como um todo. Cada pacote mantém seu próprio `CHANGELOG.md` no repositório do GitHub — este aqui é o resumo cross-pacote. +## 2026-05 — Novos pacotes de infraestrutura e integração analítica + +- **`quantilica-cloud`** lançado: plugin CLI para sincronizar manifestos de download com o catálogo na nuvem. Registrado via `quantilica.commands`; acessível como `quantilica cloud login/sync/status`. Offline-first por design. +- **`quantilica-catalog`** lançado: modelo de observação canônico (star schema) com adaptadores para BCB-SGS, RTN, INMET, Tesouro Direto e SIDRA. Resolve o cruzamento multi-fonte com um único `JOIN` em `indicator_id + geo_id + date`. +- **`quantilica-io` integrado nos fetchers**: `bcb-sgs-fetcher`, `rtn-fetcher` e `inmet-fetcher` agora exportam Parquet tipado via `save_parquet` / `write_to_parquet` com `DataContract` e manifesto embutido no header. +- **`bcb-sgs-fetcher` padronizado** para as convenções do workspace: logging estruturado, `HttpClient` em `data.py`, `ScraperClient` mantido com httpx direto por precisar de sessão stateful. + ## 2026-05 — Reescrita do portal de documentação - Portal reestruturado com narrativa de três atos no `index.md`. diff --git a/docs/fundacoes/index.md b/docs/fundacoes/index.md index 753e9f4..f4e6acd 100644 --- a/docs/fundacoes/index.md +++ b/docs/fundacoes/index.md @@ -50,3 +50,27 @@ Veja a [Arquitetura do Ecossistema](../concepts/arquitetura.md) para o desenho c ## E o host de CLI? [`quantilica-cli`](quantilica-cli.md) é o ponto de entrada unificado do ecossistema: descobre fetchers instalados via entry points e os monta como subcomandos. Não é uma fundação no sentido de "todo coletor depende dela" — é um **host** que consome os fetchers. Foi incluído na seção Fundações por afinidade arquitetural (compartilha o mesmo padrão de design domain-neutral). + +## `quantilica-cloud` — sincronização com a nuvem + +Plugin opt-in que sincroniza os manifestos de download locais com um catálogo na nuvem. Registrado sob `quantilica.commands`, expõe os subcomandos `quantilica cloud login`, `quantilica cloud sync` e `quantilica cloud status`. A coleta de dados nunca depende deste pacote. + +→ [Documentação completa](quantilica-cloud.md) + +## `quantilica-catalog` — modelo canônico de observações + +Resolve o cruzamento multi-fonte: define um star schema comum (`fact_observation` + dimensões de indicador e geográfica) e adaptadores que convertem DataFrames de cada fetcher para esse formato. Torna qualquer `JOIN` entre IBGE, BCB, INMET e demais fontes trivial. + +→ [Documentação completa](quantilica-catalog.md) + +--- + +## Visão geral das camadas de infraestrutura + +| Camada | Pacote | Depende de | Para quem | +|---|---|---|---| +| I/O resiliente | `quantilica-core` | stdlib + httpx | todo coletor | +| Analítica | `quantilica-io` | core + Polars + PyArrow | quem processa para análise | +| CLI | `quantilica-cli` | core | quem usa a linha de comando | +| Nuvem | `quantilica-cloud` | core + cli (runtime) | quem quer sincronizar manifestos | +| Catálogo | `quantilica-catalog` | io + Polars | quem cruza múltiplas fontes | diff --git a/docs/fundacoes/quantilica-catalog.md b/docs/fundacoes/quantilica-catalog.md new file mode 100644 index 0000000..fdd75e7 --- /dev/null +++ b/docs/fundacoes/quantilica-catalog.md @@ -0,0 +1,181 @@ +--- +title: quantilica-catalog +description: Modelo de observação canônico e catálogo unificado para cruzamento de dados de múltiplas fontes brasileiras. +--- + +# `quantilica-catalog` + +Modelo de dados canônico e adaptadores para normalizar observações de diferentes fontes num esquema unificado. Resolve o problema central do cruzamento de dados: cada fonte usa estrutura, nomes de colunas e granularidade geográfica diferentes. + +> **O problema:** SIDRA usa `localidade`, BCB-SGS não tem geografia, INMET usa código de estação. Para cruzar um índice BCB com dados climáticos do INMET, você precisa de um modelo comum. `quantilica-catalog` fornece esse modelo. + +## Instalação + +```bash +uv add "quantilica-catalog @ git+https://github.com/Quantilica/quantilica-catalog.git" +``` + +## O Modelo: Star Schema + +O catálogo organiza os dados em um star schema com uma tabela fato e dimensões de suporte: + +``` +fact_observation (o que? quando? onde? quanto?) +├── dim_indicator — metadados do indicador (nome, categoria, frequência) +├── dim_geo_entity — entidades geográficas (estados, municípios, estações) +├── dim_geo_relationship — hierarquias entre entidades geográficas +└── dim_geo_code — códigos externos (IBGE, INMET, etc.) +``` + +## Tabela Fato: `fact_observation` + +Cada linha responde: *qual foi o valor do indicador X no tempo T no lugar G?* + +```python +from quantilica_catalog import OBSERVATION_CONTRACT +# Schema: indicator_id (Utf8), date (Date), geo_id (Utf8?), +# value (Float64?), date_end (Date?) +``` + +| Campo | Tipo | Descrição | +|---|---|---| +| `indicator_id` | `Utf8` | `"fonte:id"` — ex.: `"bcb-sgs:433"`, `"sidra:1705:93"` | +| `date` | `Date` | Data de início da observação | +| `geo_id` | `Utf8?` | `null` para séries nacionais sem desagregação geográfica | +| `value` | `Float64?` | Valor numérico | +| `date_end` | `Date?` | Data de fim (séries com intervalo, ex.: trimestres móveis) | + +## Adaptadores + +Os adaptadores convertem DataFrames no formato de cada fetcher para o formato canônico: + +```python +from quantilica_catalog.adapters.bcb_sgs import to_observations as sgs_obs +from quantilica_catalog.adapters.sidra import to_observations as sidra_obs +import polars as pl + +# BCB-SGS → observações canônicas (sem geo_id — série nacional) +df_sgs = pl.read_parquet("series_433.parquet") # formato SGS_CONTRACT +obs = sgs_obs(df_sgs) +# indicator_id="bcb-sgs:433", geo_id=null +``` + +Adaptadores disponíveis e formato do `indicator_id` gerado: + +| Módulo | Fonte | Formato do `indicator_id` | +|---|---|---| +| `adapters.bcb_sgs` | BCB-SGS | `"bcb-sgs:{series_id}"` | +| `adapters.rtn` | Tesouro Nacional RTN | `"rtn:{planilha}:{coluna}"` | +| `adapters.inmet` | INMET BDMEP | `"inmet:{variável}"` | +| `adapters.tesouro_direto` | Tesouro Direto | `"td:{tipo_titulo}"` | +| `adapters.sidra` | IBGE SIDRA | `"sidra:{agregado_id}:{variavel_id}"` (ou `:{categoria_ids}` se classificado) | + +!!! note "SIDRA com categorias" + Quando o agregado SIDRA tem classificações (ex.: desemprego por faixa etária), o `indicator_id` inclui os IDs das categorias separados por `|`: `"sidra:1705:93:49223|49702"`. + +## Dimensão de Indicadores + +```python +from quantilica_catalog import IndicatorEntry, DataCategory, Frequency, entries_to_frame + +entries = [ + IndicatorEntry( + indicator_id="bcb-sgs:433", + source_id="bcb", + source_dataset_id="sgs", + name="IPCA — Variação mensal", + category=DataCategory.PRICES, + unit="%", + frequency=Frequency.MONTHLY, + ), +] + +dim_df = entries_to_frame(entries) +``` + +**Categorias** (`DataCategory`): `monetary`, `fiscal`, `financial`, `climate`, `labor`, `trade`, `health`, `demographic`, `economic`, `prices`. + +**Frequências** (`Frequency`): `hourly`, `daily`, `weekly`, `monthly`, `quarterly`, `semi_annual`, `rolling_quarterly`, `yearly`, `multi_year`, `irregular`. + +## Dimensão Geográfica + +### Entidades — `dim_geo_entity` + +```python +from quantilica_catalog import GeoEntityEntry, GeoType, state_id, municipality_id + +entries = [ + GeoEntityEntry(geo_id=state_id("SP"), geo_type=GeoType.TERRITORY, name="São Paulo"), + GeoEntityEntry(geo_id=municipality_id("3550308"), geo_type=GeoType.TERRITORY, name="São Paulo"), +] +``` + +**Construtores de `geo_id`:** + +| Função | Exemplo de saída | +|---|---| +| `country_id()` | `"BR"` | +| `region_id("1")` | `"BR:R:1"` | +| `state_id("SP")` | `"BR:SP"` | +| `mesoregion_id("3515")` | `"BR:MR:3515"` | +| `microregion_id("35061")` | `"BR:MCR:35061"` | +| `municipality_id("3550308")` | `"BR:M:3550308"` | +| `district_id("355030805")` | `"BR:D:355030805"` | +| `census_sector_id("350030805000001")` | `"BR:CS:350030805000001"` | +| `station_id("INMET", "A701")` | `"INMET:A701"` | + +### Hierarquias — `dim_geo_relationship` + +```python +from quantilica_catalog import GeoRelationshipEntry, RelType, GeoSystem + +rel = GeoRelationshipEntry( + from_geo_id=municipality_id("3550308"), + to_geo_id=state_id("SP"), + rel_type=RelType.ADMINISTRATIVE_PARENT, + system=GeoSystem.IBGE_TRADITIONAL, +) +``` + +**Tipos de relação** (`RelType`): `administrative_parent`, `contains`, `overlaps`, `borders`. + +**Sistemas** (`GeoSystem`): `ibge_traditional`, `ibge_rgint`, `ibge_census`, `datasus_health`, `ana_hydrographic`, `inmet`. + +### Códigos externos — `dim_geo_code` + +```python +from quantilica_catalog import GeoCodeEntry + +code = GeoCodeEntry(geo_id=state_id("SP"), system="ibge", code="35") +``` + +## DDL PostgreSQL + +Para criar as tabelas de dimensão geográfica num banco PostgreSQL: + +```python +from sqlalchemy import text +from quantilica_catalog.sql.ddl import CREATE_ALL_GEO_TABLES + +with engine.connect() as conn: + conn.execute(text(CREATE_ALL_GEO_TABLES)) + conn.commit() +``` + +Cria `dim_geo_entity`, `dim_geo_relationship` e `dim_geo_code` com índices otimizados para lookup por código e consultas de hierarquia. + +## Por que um modelo canônico? + +Sem `quantilica-catalog`, cruzar IPCA (BCB-SGS) com temperatura por estado (INMET) exige renomear colunas de cada fonte, decidir um identificador de indicador ad hoc e alinhar a granularidade geográfica manualmente. + +O catálogo faz isso **uma vez**, tornando os dados inter-operáveis por construção: um `JOIN` em `indicator_id` + `geo_id` + `date` une qualquer par de fontes. + +## Saiba Mais + +- [quantilica-io](quantilica-io.md) — os `DataContract`s em que o catálogo se apoia +- [Proveniência & Manifestos](../concepts/proveniencia.md) — rastreabilidade dos dados +- [Cookbook — Análise econômica multi-fonte](../cookbook/analise-economica-multi-fonte.md) + +## Repositório + +[github.com/Quantilica/quantilica-catalog](https://github.com/Quantilica/quantilica-catalog) — MIT. diff --git a/docs/fundacoes/quantilica-cloud.md b/docs/fundacoes/quantilica-cloud.md new file mode 100644 index 0000000..6d2d98a --- /dev/null +++ b/docs/fundacoes/quantilica-cloud.md @@ -0,0 +1,112 @@ +--- +title: quantilica-cloud +description: Plugin CLI para sincronizar manifestos de download com o catálogo Quantilica Cloud. +--- + +# `quantilica-cloud` + +Plugin do `quantilica-cli` que sincroniza manifestos de download (`*.manifest.json`) locais com um catálogo na nuvem. A coleta de dados **nunca depende** deste pacote — sincronizar é sempre opt-in. Uma vez instalado, os comandos ficam disponíveis sob `quantilica cloud`. + +> **Por que separado?** A filosofia da Quantilica é offline-first: fetchers, manifestos e armazenamento local funcionam sem rede externa. Enviar manifestos à nuvem é uma camada adicional de conveniência, nunca uma dependência. + +## Instalação + +```bash +uv add "quantilica-cloud @ git+https://github.com/Quantilica/quantilica-cloud.git" +``` + +Requer `quantilica-cli` instalado para que os comandos `quantilica cloud` funcionem. + +## CLI + +### Autenticar + +```bash +quantilica cloud login --api-key +``` + +Grava as credenciais em `~/.quantilica/credentials.toml` com permissão restrita ao dono (`chmod 0o600`). Para apontar a um servidor próprio (self-hosted): + +```bash +quantilica cloud login --api-key --endpoint http://localhost:8000 +``` + +### Sincronizar manifestos + +```bash +# Enviar todos os manifestos na pasta /data +quantilica cloud sync --root /data + +# Só os dos últimos 7 dias +quantilica cloud sync --root /data --since 7d + +# Simular sem enviar +quantilica cloud sync --root /data --since 7d --dry-run +``` + +O sync varre recursivamente o diretório em busca de arquivos `*.manifest.json`, agrupa-os em lotes de 100 e envia via `POST /v1/manifests:batch`. O servidor é idempotente — reenviar o mesmo manifesto não duplica registros. + +### Ver status + +```bash +quantilica cloud status --root /data +``` + +Compara a contagem de manifestos locais com o catálogo na nuvem e exibe o endpoint configurado. + +## Referência de opções + +| Comando | Opção | Padrão | Descrição | +|---|---|---|---| +| `login` | `--api-key` | _(obrigatório)_ | Chave de API da Quantilica Cloud | +| `login` | `--endpoint` | `https://api.quantilica.com` | URL da API | +| `sync` | `-r / --root` | `.` (diretório atual) | Diretório raiz a varrer | +| `sync` | `--since` | _(todos)_ | Filtro por data: `7d`, `30d`, etc. | +| `sync` | `--dry-run` | `False` | Simula sem enviar | +| `status` | `-r / --root` | `.` | Diretório raiz a varrer | + +## Credenciais + +As credenciais ficam em `~/.quantilica/credentials.toml`: + +```toml +[cloud] +api_key = "sk-..." +endpoint = "https://api.quantilica.com" +``` + +Não coloque esse arquivo no controle de versão. + +## Como está registrado + +`quantilica-cloud` usa o grupo de entry points `quantilica.commands` (não `quantilica.fetchers`), por isso os comandos aparecem na raiz do CLI como `quantilica cloud`, e não como `quantilica fetch cloud`: + +```toml +[project.entry-points."quantilica.commands"] +cloud = "quantilica_cloud.plugin:app" +``` + +## Módulos + +| Módulo | Responsabilidade | +|---|---| +| `credentials` | Carga e gravação de credenciais em `~/.quantilica/credentials.toml` | +| `client` | `ManifestSyncClient` — comunica com a API REST (push e listagem) | +| `plugin` | App Typer com os comandos `login`, `sync` e `status` | + +## Princípios de Design + +1. **Offline-first** — fetchers e armazenamento local funcionam sem este pacote. +2. **Plugin, não dependência** — descoberto via entry point; o CLI não acopla diretamente. +3. **Idempotente** — reenvio do mesmo manifesto SHA-256 não duplica registros. +4. **Credenciais locais** — a chave de API fica em `~/.quantilica/`, com permissão `0o600`. + +## Saiba Mais + +- [Manifestos & Proveniência](../concepts/proveniencia.md) — o que contém um manifesto +- [quantilica-cli](quantilica-cli.md) — arquitetura do host de plugins +- [quantilica-manifests-db](https://github.com/Quantilica/quantilica-manifests-db) — servidor SaaS que recebe os manifestos + +## Repositório + +[github.com/Quantilica/quantilica-cloud](https://github.com/Quantilica/quantilica-cloud) — MIT. diff --git a/docs/index.md b/docs/index.md index af6e3e1..db267d3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -69,6 +69,8 @@ A camada de confiança entre você e os dados públicos do Brasil — para que v | **[inmet-fetcher](clima/inmet-fetcher.md)** | INMET BDMEP, séries climáticas históricas com encoding limpo | | **[quantilica-core](fundacoes/quantilica-core.md)** | A fundação: HTTP resiliente, storage atômico, manifestos SHA-256 | | **[quantilica-io](fundacoes/quantilica-io.md)** | Parquet tipado com proveniência injetada no header | +| **[quantilica-cloud](fundacoes/quantilica-cloud.md)** | Sincronização opt-in de manifestos com o catálogo na nuvem | +| **[quantilica-catalog](fundacoes/quantilica-catalog.md)** | Modelo canônico de observações para cruzamento multi-fonte | --- diff --git a/docs/status.md b/docs/status.md index e0f1327..f79fbc2 100644 --- a/docs/status.md +++ b/docs/status.md @@ -17,14 +17,14 @@ Um snapshot informal do estado conhecido das fontes oficiais brasileiras que os | Fonte | Status atual | Última verificação | Observações | |---|---|---|---| -| **IBGE SIDRA** (`apisidra.ibge.gov.br`) | ✅ estável | 2026-05-10 | Rate limit não documentado; preferir horário não-comercial | -| **IBGE Agregados v3** (`servicodados.ibge.gov.br`) | ✅ estável | 2026-05-10 | Janelas curtas de 502 em manutenção | -| **DATASUS FTP** (`ftp.datasus.gov.br`) | ⚠️ intermitente | 2026-05-10 | Cai frequentemente em horário comercial; reduzir `--threads` | -| **Tesouro Transparente CKAN** | ✅ estável | 2026-05-10 | Dataset com timestamp no nome | -| **INMET BDMEP** | ✅ estável | 2026-05-10 | ZIPs por ano; latin-1; valores `-9999` | -| **Siscomex** (Comex) | ⚠️ instável | 2026-05-10 | SSL ruim em janelas curtas; arquivos GB | -| **PDET FTP** (`ftp.mtps.gov.br`) | ⚠️ intermitente | 2026-05-10 | Cai com frequência; CAGED schema diferente em 2020+ | -| **Tesouro Nacional RTN** | ✅ estável | 2026-05-10 | Excel multi-aba publicado mensalmente | +| **IBGE SIDRA** (`apisidra.ibge.gov.br`) | ✅ estável | 2026-05-17 | Rate limit não documentado; preferir horário não-comercial | +| **IBGE Agregados v3** (`servicodados.ibge.gov.br`) | ✅ estável | 2026-05-17 | Janelas curtas de 502 em manutenção | +| **DATASUS FTP** (`ftp.datasus.gov.br`) | ⚠️ intermitente | 2026-05-17 | Cai frequentemente em horário comercial; reduzir `--threads` | +| **Tesouro Transparente CKAN** | ✅ estável | 2026-05-17 | Dataset com timestamp no nome | +| **INMET BDMEP** | ✅ estável | 2026-05-17 | ZIPs por ano; latin-1; valores `-9999` | +| **Siscomex** (Comex) | ⚠️ instável | 2026-05-17 | SSL ruim em janelas curtas; arquivos GB | +| **PDET FTP** (`ftp.mtps.gov.br`) | ⚠️ intermitente | 2026-05-17 | Cai com frequência; CAGED schema diferente em 2020+ | +| **Tesouro Nacional RTN** | ✅ estável | 2026-05-17 | Excel multi-aba publicado mensalmente | **Legenda:** - ✅ **Estável** — funciona sem intervenção; eventuais 502 curtos são normais. @@ -56,4 +56,4 @@ Encontrou uma fonte fora do ar que esta página marca como estável (ou o contr --- -*Última atualização manual desta página: 2026-05-10.* +*Última atualização manual desta página: 2026-05-17.* diff --git a/mkdocs.yml b/mkdocs.yml index a06de49..ff31508 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,7 +3,7 @@ site_description: Ferramentas resilientes em Python para extrair, normalizar e a site_author: Quantilica site_url: https://docs.quantilica.com -repo_url: https://github.com/Quantilica +repo_url: https://github.com/Quantilica/docs repo_name: Quantilica edit_uri: "" @@ -65,6 +65,8 @@ nav: - quantilica-core: fundacoes/quantilica-core.md - quantilica-io: fundacoes/quantilica-io.md - quantilica-cli: fundacoes/quantilica-cli.md + - quantilica-cloud: fundacoes/quantilica-cloud.md + - quantilica-catalog: fundacoes/quantilica-catalog.md - Domínios & Ferramentas: - IBGE (Macroeconomia):