Metadata-Version: 2.5
Name: iceberg-studio
Version: 0.1.0
Summary: Explorador web de tabelas Apache Iceberg: schema, snapshots, arquivos, time travel e SQL sobre o catálogo.
Project-URL: Repository, https://github.com/rodrigomsrocha/iceberg-query-app
Project-URL: Issues, https://github.com/rodrigomsrocha/iceberg-query-app/issues
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: apache-iceberg,duckdb,iceberg,lakehouse,pyiceberg,sql
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Database :: Front-Ends
Requires-Python: >=3.11
Requires-Dist: boto3==1.43.56
Requires-Dist: duckdb==1.5.5
Requires-Dist: fastapi==0.141.1
Requires-Dist: fsspec==2026.7.0
Requires-Dist: pyarrow==25.0.0
Requires-Dist: pyiceberg[hive,pyarrow,sql-sqlite]==0.11.1
Requires-Dist: s3fs==2026.7.0
Requires-Dist: uvicorn[standard]==0.52.1
Provides-Extra: dev
Requires-Dist: httpx==0.28.1; extra == 'dev'
Requires-Dist: pytest==9.1.1; extra == 'dev'
Requires-Dist: ruff==0.16.1; extra == 'dev'
Description-Content-Type: text/markdown

# Iceberg Studio

Explorador web de tabelas **Apache Iceberg**, no espírito de uma IDE de dados
(DataGrip/DBeaver): navegue por vários catálogos, inspecione schema, snapshots
e arquivos, rode SQL com time travel e faça a manutenção das tabelas — tudo
pelo navegador, rodando na sua máquina.

- **Catálogos:** REST (com SigV4), Hive, Glue, SQL e Hadoop, vários ao mesmo tempo.
- **Tabela:** schema (com histórico e diff entre versões), partition spec,
  propriedades, saúde (arquivos pequenos, deletes), evolução de registros e
  tamanho por snapshot.
- **Snapshots:** linha do tempo, comparação de schema e **diff de dados**
  (linhas que entraram e saíram), tags e branches, rollback e expire com
  confirmação e auditoria.
- **SQL:** por tabela ou num editor do catálogo inteiro, com JOIN entre
  tabelas, autocomplete, formatador (Ctrl+Shift+F), exportação CSV/Parquet e
  time travel (`VERSION AS OF 'tag'`, `TIMESTAMP AS OF '...'`).
- **Manutenção:** política de retenção de snapshots com prévia, evolução de
  schema e comandos prontos de limpeza física pra Spark/Trino.

## Instalação

Precisa só do [uv](https://docs.astral.sh/uv/) — ele baixa o Python certo
sozinho se a máquina não tiver:

```bash
# Linux / macOS
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```

E então:

```bash
uvx iceberg-studio
```

Sobe o servidor e abre o navegador em `http://127.0.0.1:8000/ui/`. Pra
instalar de vez (fica o comando `iceberg-studio` no PATH):

```bash
uv tool install iceberg-studio      # ou: pipx install iceberg-studio
uv tool upgrade iceberg-studio      # atualizar
```

Opções:

| Opção | O que faz |
|---|---|
| `--port 8080` | porta (padrão 8000; ocupada, usa a próxima livre) |
| `--host 0.0.0.0` | escutar na rede — veja [Segurança](#segurança) antes |
| `--data-dir ~/outro` | onde guardar catálogos e auditoria |
| `--no-browser` | não abre o navegador |
| `--version` | versão instalada |

Os catálogos que você cadastra e a trilha de auditoria ficam em
`~/.iceberg-studio` (ou `--data-dir` / `ICEBERG_APP_DATA_DIR`). Atualizar ou
reinstalar o app não apaga nada lá.

## Segurança

Feito pra uso local: CORS fechado pra outros domínios e **sem login**. Fora do
localhost, qualquer um que alcançar a porta acessa os catálogos configurados.
Antes de expor na rede, configure:

- `ICEBERG_APP_API_KEY` — exige o header `X-API-Key` em toda rota sob
  `/catalogs`. A UI pergunta a chave uma vez e guarda no navegador.
- `ICEBERG_APP_ALLOWED_ORIGINS` — origens (separadas por vírgula) autorizadas a
  chamar a API via JavaScript de outro domínio. Vazio = nenhuma.

Segredos de catálogo (`s3.secret-access-key`, tokens, senhas) ficam em texto no
`catalogs.json`; pra evitar isso, use `${ENV:NOME_DA_VAR}` como valor da
propriedade — é resolvido do ambiente na hora de conectar.

## Desenvolvimento

```bash
# backend + ferramentas de teste (instala o projeto em modo editável)
pip install -r requirements-dev.txt

# frontend: build de produção, embutida no pacote em iceberg_studio/web/
cd frontend && npm install && npm run build && cd ..

# sobe API + UI (também dá: iceberg-studio)
uvicorn iceberg_studio.main:app --reload --port 8000
```

Rodando do código-fonte, os dados ficam em `config/` na raiz do projeto, em vez
de `~/.iceberg-studio`.

Frontend com hot reload (http://localhost:5173, com proxy pro backend em
localhost:8000):

```bash
cd frontend && npm run dev
```

Testes:

```bash
pytest                       # backend (catálogo e warehouse temporários; não toca no config/)
cd frontend && npm test      # frontend (vitest)
```

### Publicar uma versão

1. Suba `version` no `pyproject.toml` e faça o commit.
2. Crie e envie a tag correspondente:
   ```bash
   git tag v0.2.0 && git push origin v0.2.0
   ```
3. O workflow `Release` builda o frontend, gera o pacote, testa o pacote
   instalado, publica no PyPI e cria a release no GitHub com os arquivos.

A publicação usa **Trusted Publishing** (sem token guardado). Configuração
única, em https://pypi.org/manage/account/publishing/ → *Add a new pending
publisher*:

| Campo | Valor |
|---|---|
| PyPI Project Name | `iceberg-studio` |
| Owner | `rodrigomsrocha` |
| Repository name | `iceberg-query-app` |
| Workflow name | `release.yml` |
| Environment name | `pypi` |

## API

A UI usa a mesma API HTTP, que também pode ser chamada direto. Rotas de tabela
ficam sob `/catalogs/{catalogo}/tables/{namespace}/{tabela}`.

| Método | Rota | O que faz |
|---|---|---|
| GET | `/catalogs` | catálogos configurados |
| POST / DELETE | `/catalogs`, `/catalogs/{catalogo}` | registra / remove um catálogo |
| GET | `/catalogs/{catalogo}/tables` | tabelas do catálogo (`"namespace.tabela"`) |
| POST | `/catalogs/{catalogo}/query` | SQL sobre o catálogo inteiro (JOIN, `VERSION AS OF`) |
| POST | `/catalogs/{catalogo}/query/export` | o mesmo, exportado em CSV ou Parquet |
| GET | `…/metadata`, `…/snapshots`, `…/files`, `…/manifests`, `…/partitions`, `…/column-metrics` | metadados da tabela |
| POST | `…/query`, `…/query/export` | SQL sobre a tabela, com `snapshot_id` opcional |
| GET | `…/snapshots/diff?from_snapshot_id=…&to_snapshot_id=…` | linhas adicionadas/removidas entre snapshots |
| POST | `…/rollback`, `…/expire-snapshot` | rollback / expirar um snapshot |
| POST | `…/refs`, `…/refs/{nome}/remove` | cria / remove tag ou branch |
| POST | `…/schema/changes` | adiciona coluna, renomeia, promove tipo |
| POST | `…/properties` | define / remove propriedades |
| GET / POST | `…/retention`, `…/retention/apply` | prévia / aplicação da política de retenção |
| GET | `…/audit-log` | auditoria das escritas na tabela |

Toda escrita exige `actor` (quem fez) e, nas destrutivas, a confirmação do nome
da tabela; tudo fica na auditoria. Exemplo:

```bash
curl -X POST http://localhost:8000/catalogs/local/query \
  -H "Content-Type: application/json" \
  -d '{"sql": "select status, count(*) from ecommerce.orders version as of '"'"'v1'"'"' group by status"}'
```

## Estrutura

```
iceberg_studio/         - backend (FastAPI), publicado como o pacote iceberg-studio
  cli.py                - comando `iceberg-studio`
  main.py               - monta o app: CORS, routers e a interface em /ui
  settings.py           - configuração via ambiente (diretório de dados, CORS)
  api/                  - rotas HTTP (catálogos, tabelas), modelos e dependências
  services/             - casos de uso (escritas auditadas, retenção, schema, refs)
  catalogs/             - registro de catálogos, tipos suportados, adapters, SigV4
  query.py              - SQL via DuckDB sobre scans Arrow (time travel, exportação)
  snapshot_diff.py      - diff de dados entre snapshots
  retention.py          - política de retenção de snapshots
  web/                  - build do frontend (gerada, fora do git)
frontend/               - SPA React + Vite + TypeScript + Tailwind v4
tests/                  - pytest, espelhando iceberg_studio/
config/                 - estado local ao rodar do código-fonte (fora do git)
```

## Limitações conhecidas

- **Limpeza física:** o PyIceberg não apaga arquivos nem compacta dados.
  Expirar snapshots remove só os metadados; o app gera os comandos de Spark/Trino
  pra limpeza física.
- **ORC:** a leitura de data files em ORC é limitada no PyIceberg.
- **Um usuário por instância:** não há login; o "ator" da auditoria é um nome
  digitado.

## Licença

[Apache 2.0](LICENSE).
