Varredura de engenharia: notebooks, jobs, pipelines e DDL no Databricks e no Snowflake
A qualidade dos dados depende do código que os produz. Numa conexão Databricks ou Snowflake, o
BeryX pode ler também os notebooks, os jobs, os pipelines, os modelos ML e o DDL de views, tasks,
streams e procedures, e procurar neles práticas de risco: credenciais escritas no código,
SELECT *, jobs agendados sem retry, timeout ou alerta, notebooks que escrevem tabelas sem job
nenhum, escrita na camada Gold a partir da Bronze, tasks suspensas, streams stale e warehouses
sem auto-suspend.
Cada heurística que encontra alguma coisa abre um problema do tipo «Engenharia», com a lista
dos ativos afetados. Um workspace com 300 notebooks com SELECT * tem um problema de prática, e
não 300.
A varredura é opt-in por conexão e só lê. No Databricks faz apenas pedidos
GETàs APIs oficiais; no Snowflake só correSHOWeSELECTde catálogo. O código lido não fica guardado: os problemas levam o tipo de achado, o nome do ativo e a linha, e o valor de uma credencial nunca é mostrado nem gravado.
O que lê
A varredura usa as credenciais da própria conexão. Cada coleção é lida à parte: se o token ou o papel não tiver acesso a uma delas, essa coleção fica de fora, a varredura continua e o painel mostra-a em «Cobertura parcial».
Databricks
Com o host e o token da conexão, só pedidos GET, pelo mesmo cliente HTTP só de leitura e com a
mesma guarda anti-SSRF dos outros conectores:
| API | O que traz |
|---|---|
Workspace API (/api/2.0/workspace/list e /workspace/export, formato SOURCE) |
Os notebooks e o código de cada um |
Jobs API 2.1 (/api/2.1/jobs/list e /jobs/runs/list) |
Agendamento, retries, timeouts, alertas de falha, notebooks de cada task e o estado do último run |
Pipelines (/api/2.0/pipelines) |
Estado e última atualização dos pipelines DLT e Lakeflow, e os notebooks de cada um |
MLflow Model Registry (/api/2.0/mlflow/registered-models/search) |
A data da versão mais recente de cada modelo |
O token precisa de leitura nas pastas do workspace, nos jobs, nos pipelines e no Model Registry que queres analisar. O que não conseguir ler fica em «Cobertura parcial».
Snowflake
Com o utilizador e o papel da conexão, só comandos de catálogo. Antes de chegar ao driver, cada
comando passa por uma guarda que recusa tudo o que não seja um único SHOW, SELECT ou
DESCRIBE:
| Comando | O que traz |
|---|---|
SHOW WAREHOUSES |
Tamanho e auto-suspend de cada warehouse |
SHOW TASKS IN DATABASE |
Estado, agendamento, SQL e data da última suspensão |
SHOW STREAMS IN DATABASE |
Se o stream está stale |
SHOW MATERIALIZED VIEWS IN DATABASE |
A definição de cada materialized view |
INFORMATION_SCHEMA.PROCEDURES |
O corpo de cada procedure |
INFORMATION_SCHEMA.VIEWS, com GET_DDL quando a definição vem vazia |
A definição de cada view |
O papel só vê os objetos sobre os quais tem algum privilégio. Nunca há SELECT sobre dados de
tabelas.
O que procura
Um problema por heurística e por conexão, com até 50 ativos listados (a contagem é a total):
| Heurística | Severidade | Fonte | O que deteta |
|---|---|---|---|
hardcoded_secret |
crítica | ambas | Credenciais escritas no código (token Databricks, chave de acesso AWS, chave privada, token GitHub ou Slack, chave de API de LLM, password numa connection string ou num literal). Mostra o tipo e a linha, nunca o valor. Placeholders e leituras de cofres (dbutils.secrets, variáveis de ambiente) não contam |
gold_direct_write |
aviso | ambas | Um notebook, uma view ou outro objeto SQL escreve (ou define) uma tabela Gold a ler diretamente da Bronze, sem passar pela Silver. A camada sai do nome do schema ou da tabela (gold, mart, bronze, raw, landing…) |
select_star |
info | ambas | SELECT * em notebooks e no SQL de views, procedures e tasks: uma coluna nova, removida ou renomeada a montante muda o que chega a jusante sem ninguém dar por isso |
job_no_retry |
aviso | Databricks | Job agendado e ativo com alguma task sem max_retries |
job_no_timeout |
aviso | Databricks | Job agendado e ativo sem timeout_seconds no job nem em todas as tasks |
job_no_alert |
aviso | Databricks | Job agendado e ativo sem notificação on_failure, nem no job nem nas tasks |
job_failing |
aviso | Databricks | O último run do job terminou em falha |
pipeline_failing |
aviso | Databricks | Pipeline DLT ou Lakeflow com o estado ou a última atualização em falha |
orphan_notebook |
info | Databricks | Notebook que escreve tabelas e que nenhum job nem pipeline executa. Só é avaliado quando os jobs e os pipelines foram listados até ao fim |
task_suspended |
aviso | Snowflake | Task suspensa há mais de 30 dias |
stream_stale |
aviso | Snowflake | Stream stale: perdeu o offset e há alterações que já não se consomem |
model_stale |
aviso | Databricks | Modelo ML cuja versão mais recente tem mais de 90 dias |
warehouse_no_autosuspend |
aviso | Snowflake | Warehouse sem auto-suspend ou com mais de 60 minutos |
A cada varredura, um problema que persiste é atualizado (um «reconhecido» continua reconhecido), um que desaparece passa a resolvido e um novo é criado. Desativar a varredura resolve os problemas de engenharia abertos da conexão.
A mesma leitura dos notebooks propõe também regras candidatas: as asserções escritas no
código (assert, validações com raise, dropna, dropDuplicates) passam a sugestões de regra
para as tabelas que o BeryX já conhece, com o trecho anonimizado como evidência. Aparecem em
Sugestões com a origem «Minerada em notebooks».
Ativar e pedir na app
- Em Conexões, o cartão de uma conexão Databricks ou Snowflake tem a linha «Varredura de engenharia», com o estado (ativada ou desativada) e o número de achados abertos. Carrega em Abrir.
- No painel, um administrador carrega em Ativar varredura.
- Com a varredura ativada, carrega em Pedir varredura. Se quiseres, marca antes Juntar um resumo por IA (ver O que sai para a IA).
- A varredura corre em segundo plano. O painel volta a ler o estado até ela terminar e mostra os achados abertos por heurística, o que foi lido (notebooks, jobs, views…) e o que ficou de fora.
- Ver os achados de engenharia em Problemas abre
/problemas?type=engineering, com o filtro «Engenharia (notebooks, jobs, DDL)» já aplicado. Cada achado do painel também leva ao seu problema.
Uma API ou um comando recusado só deixa essa coleção de fora. Uma varredura que falhe, por exemplo sem ligação à fonte, não deixa registo no painel: testa a conexão e pede de novo.
Pela API
Três endpoints na conexão:
| Método e caminho | Para quê | Quem |
|---|---|---|
GET /api/v1/connections/{id}/engineering |
Estado: enabled, supported, a última varredura (last_scan, com inventário, notas, telemetria e resumo) e os problemas abertos (issues) |
Qualquer papel do workspace, também com um token de API |
PATCH /api/v1/connections/{id}/engineering |
Ativar ou desativar: {"enabled": true} |
Administradores |
POST /api/v1/connections/{id}/engineering/scan |
Pedir a varredura: {"llm_summary": false} |
Administradores e membros |
# Estado (um token dvk_* de leitura chega)
curl -s "$DATAVAULT_API_URL/api/v1/connections/$CONNECTION_ID/engineering" \
-H "Authorization: Bearer $DATAVAULT_TOKEN"
# Ativar e pedir a varredura (sessão de um administrador)
curl -s -X PATCH "$DATAVAULT_API_URL/api/v1/connections/$CONNECTION_ID/engineering" \
-H "Authorization: Bearer $SESSION" -H "Content-Type: application/json" -d '{"enabled": true}'
curl -s -X POST "$DATAVAULT_API_URL/api/v1/connections/$CONNECTION_ID/engineering/scan" \
-H "Authorization: Bearer $SESSION" -H "Content-Type: application/json" -d '{"llm_summary": false}'
- Os tokens de API
dvk_*são de leitura: servem para oGET. OPATCHe oPOSTfazem-se na app ou com a sessão de um utilizador. - O
POSTresponde409com a varredura desativada ou dentro de uma janela de blackout da conexão («Boa vizinhança»). OPATCHresponde400ao ativar numa conexão que não seja Databricks nem Snowflake. - Em produção, o
POSTpõe a varredura na fila e responde{"status": "queued"}. Sem fila (instalação de desenvolvimento), corre logo e responde{"status": "completed", …}com os achados. - Ativar e desativar ficam na auditoria do workspace.
O que é só leitura e o que fica guardado
- Na fonte: só pedidos
GET(Databricks) e sóSHOW/SELECT/DESCRIBEde catálogo (Snowflake). Nada é criado, alterado ou executado na fonte. - No BeryX: o código lido é analisado em memória e descartado no fim da varredura. Os
problemas guardam o nome de cada ativo (caminho do notebook, nome do job,
schema.objeto) e um detalhe curto («SELECT * na linha 12», «token Databricks (linha 4)»). Um nome com aspeto de credencial também é substituído antes de ser gravado. - Telemetria: o número de pedidos, os bytes lidos e a duração ficam no registo da varredura, ao lado dos limites usados.
O que sai para a IA
Só quando pedes Juntar um resumo por IA (llm_summary: true), e só se houver achados.
- O que recebe: a fonte (Databricks ou Snowflake), as contagens do inventário e, para no máximo 15 heurísticas, o nome, a severidade, o título, a contagem e até cinco exemplos (tipo, nome e detalhe do ativo). Tudo passa antes pela remoção de credenciais e de emails.
- O que nunca recebe: o código, o conteúdo dos notebooks e o valor de uma credencial.
- Pastas pessoais: no Databricks, o caminho de um notebook pessoal tem o email do dono
(
/Users/<email>/…). Segue como/Users/<utilizador>/…, e qualquer outro email como<email>. - Classe de dados:
metadata_only. A tarefa chama-se «Varredura de engenharia» na Política de IA do workspace: com a IA desligada não há resumo, e os modelos permitidos, a chave própria e as rotas BYOK valem também para ela. Por omissão vai para o Claude Haiku da Anthropic. - Custo: conta no orçamento de IA do workspace, como as outras tarefas.
- Sem fornecedor disponível, com o orçamento esgotado ou com a IA desligada, a varredura corre na mesma e o painel diz porque não há resumo. O resumo aparece com o selo «Conteúdo gerado por IA».
Quem pode fazer o quê
| Ação | Administrador | Membro | Leitor |
|---|---|---|---|
| Ver o estado e os achados | sim | sim | sim |
| Pedir a varredura | sim | sim | não |
| Ativar ou desativar | sim | não | não |
Não há limite por plano: a varredura está em todos os planos e não conta na quota de scans. O resumo por IA conta no orçamento de IA do plano.
Limites
Cada varredura tem tetos, para não pesar na fonte nem prender o worker. A conexão pode baixar ou
subir cada um com engineering_limits no config enviado pela API ao criar a conexão, nunca acima
do teto. A app não tem campo para isto.
| Limite | Por omissão | Teto |
|---|---|---|
max_notebooks |
200 | 1000 |
max_notebook_bytes |
200 000 | 1 000 000 |
max_jobs |
200 | 1000 |
max_objects |
500 | 2000 |
max_requests |
400 | 2000 |
timeout_s |
120 | 600 |
- Um limite atingido aparece em «Cobertura parcial» e deixa a coleção incompleta. Com os jobs ou
os pipelines incompletos, a heurística
orphan_notebooknão é avaliada. - Ao chegar ao
timeout_sou aomax_requests, a varredura para e guarda o que já leu. Um pedido pendurado que passe dotimeout_smais 60 segundos faz falhar a varredura sem guardar nada. - O
SELECT *, os segredos e a camada Gold/Bronze leem-se por padrões no texto, sem executar o código: um nome montado em tempo de execução escapa, e um falso positivo é possível. - A camada sai só dos nomes. Um lakehouse sem
bronze,silverougold(ou equivalentes) nos nomes não tem achadosgold_direct_write.