Saltar para o conteúdo
BeryX
Voltar às respostas para RFP

Documentação do BeryX

Catálogo externo — publicar a qualidade no OpenMetadata, no DataHub, no Collibra e no Microsoft Purview (CATSYNC v1/v2/v3, cartão #398)

O BeryX publica, no fim de cada scan, o veredito, o score e o resultado de cada regra como testes de Data Quality no OpenMetadata do cliente. Quem vive no catálogo passa a ver a qualidade medida pelo BeryX na aba Data Quality / Profiler da própria tabela — sem abrir outra ferramenta.

Desde o CATSYNC v2 o mesmo push também publica no DataHub (assertions) — ver DataHub — e desde o CATSYNC v3 no Collibra (assets «Data Quality Metric» pela Import API) — ver Collibra. No Microsoft Purview (cartão #398) o veredito vai para atributos da própria tabela no Data Map — ver Microsoft Purview. Os catálogos partilham tudo exceto o cliente HTTP: mapeamento por conexão, conteúdo publicado, limites, retry, best-effort e API.

Read-only nas fontes mantém-se: o BeryX escreve só no catálogo que o admin ligou (opt-in por conexão) e só entidades próprias — no OpenMetadata, entidades de Data Quality com prefixo datavault (definições, test cases e resultados); no DataHub, assertions datavault-*; no Collibra, assets «Data Quality Metric» DataVault:*; no Purview, os atributos personalizados datavault_* da entidade da tabela. Nunca altera tabelas, owners, tags, glossário nem lineage.

No sentido inverso, o BeryX também lê a curadoria do catálogo (domínios, owners, tags de sensibilidade e descrições) — ver Ler do catálogo. Essa leitura nunca escreve no catálogo.

O que aparece no OpenMetadata

Por cada dataset do scan com FQN mapeado e tabela existente no catálogo:

Test case Nível Estado Resultado
datavault_quality tabela Success se o veredito é pass/warn, Failed se fail, Aborted sem regras «Veredito BeryX AVISO · score 82.5 · 2 regra(s) falhada(s)» + valores verdict, score, failed_rules
datavault_<tipo>_<id> coluna (ou tabela) Failed / Success severidade, valor observado e limiar
  • O veredito é o mesmo do gate de CI (GET /datasets/{id}/verdict): fail = regra crítica falhada ou contrato ODCS inválido; warn = só warnings. warn publica Success no test case do veredito (o catálogo não tem estado de aviso) — as regras em aviso aparecem como Failed nos seus test cases.
  • Regras que voltam a passar publicam Success: o histórico no OpenMetadata mostra quando o problema apareceu e quando foi resolvido.
  • Limites por push: 200 datasets, 50 regras por dataset (falhadas primeiro).
  • Só metadados e agregados (nomes de regras/colunas, contagens, min/max, score). Nunca linhas nem amostras.

Setup (10 minutos)

1. Criar o bot no OpenMetadata

  1. Settings → Bots → Add bot — ex.: datavault-bot.
  2. Atribui-lhe um papel que permita criar e editar testDefinition, testCase (e respetivos resultados) e ler table — ex.: um papel DataVaultPublisher com uma política só com essas regras. Não precisa de mais nada: o BeryX não toca noutras entidades.
  3. Copia o JWT token do bot.

2. Ligar o servidor no BeryX

Conexões → cartão da fonte → Catálogo externo → Ligar catálogo:

  • URL do servidor: https://openmetadata.empresa.pt (aceita também …/api ou …/api/v1).
  • Token do bot: o JWT do passo 1. É cifrado (Fernet) antes de gravar e nunca volta a ser mostrado nem aparece em logs.
  • «Ligar e testar» confirma URL e token (GET /api/v1/users/loggedInUser).

O URL passa pela proteção anti-SSRF: endereços privados/internos são recusados. Um OpenMetadata na rede interna do cliente (ex.: BeryX self-hosted no mesmo perímetro) exige o host em DATAVAULT_CONNECTOR_ALLOWED_HOSTS.

3. Mapear os datasets para FQNs

No OpenMetadata o FQN de uma tabela é serviço.base.schema.tabela. Na conexão indica o prefixo FQN — o serviço e a base desta fonte — e o BeryX acrescenta schema.tabela:

Fonte no BeryX Prefixo FQN Dataset FQN publicado
PostgreSQL analytics postgres_prod.analytics crm.clientes postgres_prod.analytics.crm.clientes
Snowflake DWH snowflake_prod.DWH SALES.ORDERS snowflake_prod.DWH.SALES.ORDERS
CSV / SQLite (sem schema) files.default.default vendas files.default.default.vendas

Nomes com . são citados como no OpenMetadata ("v1.2").

Exceções (opcional), uma por linha, dataset = FQN:

crm.clientes = dwh_prod.core.crm.customers
staging.tmp_import =

Sem FQN depois do =, o dataset não é publicado.

4. Validar

«Publicar agora» reenvia o último scan concluído da conexão e mostra o estado:

  • publicado — todos os datasets mapeados foram publicados;
  • publicado em parte — alguns datasets sem FQN, sem tabela no catálogo (FQN errado?) ou com erro; a mensagem lista os primeiros;
  • falhou — nada publicado (token revogado, servidor em baixo, nenhum FQN encontrado).

Daí em diante, cada scan concluído publica automaticamente (desliga com «Publicar automaticamente no fim de cada scan»).

Comportamento em falha

  • Best-effort: o push corre no worker depois de o scan ficar completed. Nenhum erro do catálogo falha, atrasa o estado ou repete o scan.
  • Retry leve: erros de rede, 429 e 5xx são repetidos 2 vezes (0,5 s e 1,5 s). 4xx são definitivos. Após 3 datasets seguidos com erro e nenhum sucesso, o push para (catálogo em baixo / token revogado) em vez de martelar o servidor.
  • Erros ficam no estado da conexão e no log catalog_push_* — sempre sem o token (as mensagens do servidor passam por scrub).
  • Compatível com OpenMetadata ≥ 1.5 (POST /dataQuality/testCases/testCaseResults/{fqn}) e com versões 1.x anteriores (PUT /dataQuality/testCases/{fqn}/testCaseResult, usado automaticamente quando o endpoint novo devolve 404).

API

Método Caminho Quem
GET /catalog-integrations membros
POST /catalog-integrations {name, kind: "openmetadata" | "datahub" | "collibra" | "purview", api_url, token} (+ username, community, domain no Collibra; + tenant_id, client_id no Purview, com o client secret em token) admin
POST /catalog-integrations/{id}/test admin
DELETE /catalog-integrations/{id} (apaga também os mapeamentos) admin
GET /catalog-syncs (estado de todas as conexões) membros
GET /connections/{id}/catalog-sync membros
PUT /connections/{id}/catalog-sync {integration_id, fqn_prefix, overrides, enabled} admin
DELETE /connections/{id}/catalog-sync admin
POST /connections/{id}/catalog-sync/push admin

Todas as alterações ficam no trilho de auditoria (catalog_integration_*, catalog_sync_*).

DataHub (CATSYNC v2)

Mesmo desenho, pelo endpoint oficial do REST emitter do DataHub (GMS). O BeryX escreve só entidades assertion próprias (urn:li:assertion:datavault-<hash>, determinístico por dataset + teste — cada scan atualiza a mesma assertion) com dois aspetos:

Aspeto Conteúdo
assertionInfo type: DATASET, datasetAssertion com o URN do dataset, scope DATASET_COLUMN (+ fields = schemaField da coluna) ou DATASET_ROWS, operator: _NATIVE_, nativeType datavault_<tipo> / datavault_quality_verdict; source: EXTERNAL; descrição
assertionRunEvent resultado deste scan: SUCCESS / FAILURE / ERROR (sem regras), nativeResults com a mensagem + verdict, score, failed_rules ou severity, rule_type

Os testes publicados são os mesmos do OpenMetadata (veredito + uma por regra, mesmas regras de estado). As assertions aparecem na aba Quality / Validation do dataset.

Não escrevemos o aspeto testResults do dataset: pertence às Metadata Tests do próprio DataHub e seria sobrescrito. Nenhum aspeto do dataset (schema, owners, tags…) é tocado.

Pedidos (todos com Authorization: Bearer <PAT>):

POST /api/graphql                                { me }  — «Testar ligação»
GET  /aspects/{urn}?aspect=datasetKey&version=0         — dataset existe?
POST /aspects?action=ingestProposal              assertionInfo + assertionRunEvent

Setup

  1. Token: com a autenticação do metadata service ativa, cria um utilizador de serviço com permissão de editar assertions (política Edit Assertions nos datasets) e gera um Personal Access Token em Settings → Access Tokens.
  2. Ligar: Conexões → Catálogo externo → Ligar outro catálogo (ou «Ligar um catálogo»), escolhe DataHub e indica o URL do GMS — ex.: https://datahub.empresa.pt/api/gms (proxy do frontend), https://datahub-gms.empresa.pt:8080 ou https://<tenant>.acryl.io/gms (aceita também o URL terminado em /api/graphql). Mesma proteção anti-SSRF e cifra Fernet do token.
  3. Mapear: no DataHub a tabela é o URN urn:li:dataset:(urn:li:dataPlatform:<plataforma>,<nome>,<ENV>). O prefixo é plataforma[@ENV].base — o BeryX acrescenta schema.tabela ao nome (ENV por omissão PROD):
Prefixo Dataset URN publicado
postgres.analytics crm.clientes urn:li:dataset:(urn:li:dataPlatform:postgres,analytics.crm.clientes,PROD)
snowflake@DEV.dwh sales.orders urn:li:dataset:(urn:li:dataPlatform:snowflake,dwh.sales.orders,DEV)
postgres.prod-instance.analytics (platform instance no nome) crm.clientes …postgres,prod-instance.analytics.crm.clientes,PROD)

Exceções: dataset = urn:li:dataset:(…) (usado tal e qual) ou dataset = plataforma[@ENV].nome; vazio = não publicar. Prefixo/URN com sintaxe inválida é recusado ao guardar (400).

Compatibilidade: DataHub ≥ 0.12 (campos source/description do assertionInfo) e DataHub Cloud.

Collibra (CATSYNC v3)

Estado: validado com transporte simulado (a API do Collibra substituída por um servidor falso nos testes, com o CSV e o template verificados por snapshot). A validação num tenant Collibra de um cliente está pendente — até lá, confirma os três pressupostos de Por confirmar no tenant.

Pela Import REST API v2 do Collibra, como no exemplo oficial «data-quality» («Import Data Quality Metrics from an external system»): um CSV + um template JSON num único POST /rest/2.0/import/csv-job, seguido de polling do job. Ao contrário do OpenMetadata e do DataHub, que recebem um pedido por teste, o Collibra recebe um job de import por push com todos os testes do scan.

O que aparece no Collibra

Um asset do tipo OOTB Data Quality Metric por teste (veredito + uma regra por linha, as mesmas do OpenMetadata), no domínio Rulebook configurado:

Campo do asset Veredito (datavault_quality) Regra (datavault_<tipo>_<id>)
Nome completo DataVault:<id do dataset>:datavault_quality DataVault:<id do dataset>:datavault_<tipo>_<id8>
Display name clientes · veredito DataVault clientes · not_null (email)
Passing Fraction score 0-100 % de linhas que passam (ou 100/0, ver abaixo)
Threshold — % mínima para passar = 100 − limiar do BeryX
Loaded / Rows Passed / Rows Failed — contagens da regra, quando existem
Result true se pass/warn, false se fail true se passou
Description resumo + link para o dataset no BeryX + data do scan idem
Relação «complies to / applies to» (…7018) com a Table com a Column (ou a Table, se a regra é de tabela)
  • O nome completo é estável: cada scan atualiza o mesmo asset (upsert por nome + domínio da Import API) — sem estado extra no BeryX.
  • Contagens: só agregados que o motor de regras já guarda — not_null (linhas e nulos), unique (linhas e repetidas) e as regras com valores verificados/violações (pattern, membership, schema_conformity…). Regras sem contagem (frescura, volume, erro de avaliação) publicam uma métrica binária: Passing Fraction 100 se passou, 0 se falhou, sem linhas nem limiar. Nunca vão valores nem exemplos de linhas.
  • Uma célula vazia no CSV deixa o atributo por enviar (ex.: Threshold do veredito).

Pedidos

Todos com Authorization: Basic <utilizador:password> ou Bearer <JWT>:

GET  /rest/2.0/users/current                                     — «Testar ligação»
GET  /rest/2.0/assets?name=<nome completo>&nameMatchMode=EXACT   — a Table existe?
GET  /rest/2.0/relations?targetId=<table>&relationTypeId=…7042   — colunas da tabela
POST /rest/2.0/import/csv-job      multipart: file (CSV), template, separator «;», headerRow, continueOnError
GET  /rest/2.0/jobs/{jobId}                                      — polling a cada 2 s, teto de 30 s

O template declara a community e o domínio (tipo Rulebook) de destino — o import cria-os se não existirem, como no exemplo oficial — e um asset por linha do CSV identificado por nome + domínio, ligado ao asset alvo pelo id.

Setup

  1. Utilizador: um utilizador de serviço com permissão para importar e criar assets do tipo Data Quality Metric no domínio de destino (e para criar a community/domínio, se ainda não existirem), e para ver as Tables e Columns das fontes. Autenticação Basic (utilizador + password) ou um JWT do Collibra (deixar o utilizador vazio).
  2. Ligar: Conexões → Catálogo externo → Ligar um catálogo → Collibra:
    • URL do Collibra: https://empresa.collibra.com (aceita também …/rest/2.0). Mesma proteção anti-SSRF e mesma cifra Fernet (password, utilizador e JWT ficam cifrados; nunca voltam a ser mostrados nem aparecem em logs ou mensagens de erro).
    • Community de destino e Domínio de destino (Rulebook): onde ficam as métricas — ex.: Data Quality / DataVault. Recomendado um domínio Rulebook só para o BeryX.
    • «Ligar e testar» confirma URL e credenciais (GET /users/current).
  3. Mapear: no Collibra a tabela é a Table com o nome completo da convenção do Data Catalog, com > como separador. O prefixo é tudo antes de >schema>tabela:
Prefixo Dataset Table procurada
postgres_prod>analytics crm.clientes postgres_prod>analytics>crm>clientes
SQLite>erp clientes (sem schema) SQLite>erp>clientes

Exceções: dataset = <nome completo da Table> (usado tal e qual — serve para Tables registadas à mão com outros nomes); vazio = não publicar. As colunas são as Columns ligadas à Table pela relação OOTB «Column is part of Table» (…7042), comparadas pelo último segmento do nome (sem distinguir maiúsculas).

Comportamento em falha

  • Table inexistente (ou nome ambíguo — várias Tables com o mesmo nome completo): o dataset fica em «sem tabela no catálogo» e a mensagem diz porquê; nunca exceção.
  • Column inexistente: a métrica liga-se à Table e a mensagem do push lista as colunas em falta («N métrica(s) ligada(s) à tabela por falta do asset Column»).
  • Job: COMPLETED/SUCCESS → publicado; COMPLETED_WITH_ERROR (continueOnError: os comandos válidos entram) → publicado em parte, com a mensagem do Collibra; ERROR/CANCELED/FAILURE → falhou (nada do lote conta como publicado). Um job ainda a correr ao fim de 30 s fica «submetido» (não é erro): o resultado fica nas Activities do Collibra.
  • Como nos outros catálogos, nenhum erro do Collibra falha, atrasa o estado ou repete o scan. O push corre no fim do scan (sem fila própria); o erro fica no estado da conexão e no log catalog_push_* com o correlation_id do scan e o id do job — sempre sem credenciais.
  • Ler do catálogo (cartão #140) ainda não é suportado no Collibra: a opção «Importar do catálogo ao sincronizar» fica escondida e POST /connections/{id}/catalog-import/plan responde 400.

Por confirmar no tenant

O cliente HTTP segue o exemplo oficial e a especificação OpenAPI publicada no mesmo repositório (import-api-java-client/schemas/). Três pontos só um tenant real confirma:

  1. O atributo OOTB Description está atribuído ao tipo Data Quality Metric (os outros seis atributos são os do exemplo oficial). Se não estiver, o job termina COMPLETED_WITH_ERROR (publicado em parte) até a atribuição existir.
  2. Os nomes completos das Tables seguem a convenção sistema>base>schema>tabela da ingestão do Data Catalog — senão, usar exceções com o nome completo real.
  3. Uma célula vazia no CSV não apaga um valor já existente no atributo.

Microsoft Purview (cartão #398)

Estado: validado com transporte simulado. O Data Map e o login do Entra ID são substituídos por um httpx.MockTransport que aplica a semântica de substituição do createOrUpdate e recusa pedidos sem os atributos obrigatórios; o corpo do pedido tem snapshot em backend/tests/snapshots/purview/. Sem tenant Purview nesta sessão, o spike confirmou os customAttributes na especificação oficial da API do Data Map (2023-09-01, repositório Azure/azure-rest-api-specs): o modelo AtlasEntity tem customAttributes e o exemplo Entity_AddCustomAttribute usa-os em POST /atlas/v2/entity. A validação num tenant de um cliente está pendente — ver Por confirmar no tenant.

Pela API do Data Map (compatível com Apache Atlas v2), o BeryX escreve quatro atributos personalizados (customAttributes) na entidade da tabela (ATTRIBUTE_KEYS em backend/app/infra/catalog/purview.py):

Atributo Valor
datavault_score score 0-100 do último scan, com duas casas (72.50); n/a sem score
datavault_verdict pass, warn, fail ou unknown (o mesmo veredito do gate de CI)
datavault_last_scan fim do scan em UTC, ISO 8601 (2026-10-11T11:00:00Z)
datavault_url página do dataset no BeryX (app_base_url/datasets/{id})

Só o veredito sobe. As regras, uma a uma, não vão para o Purview nesta fase: o push manda-lhe só o caso do veredito (CatalogSpec.publishes_rules=False), e o estado da conexão conta um teste por dataset.

Pedidos

POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token   client credentials, scope https://purview.azure.net/.default
GET  /datamap/api/atlas/v2/types/entitydef/name/DataSet              testar a ligação
GET  /datamap/api/atlas/v2/entity/uniqueAttribute/type/{typeName}?attr:qualifiedName=…&ignoreRelationships=true&minExtInfo=true
POST /datamap/api/atlas/v2/entity?api-version=2023-09-01             createOrUpdate

O createOrUpdate é uma atualização completa da entidade. Para não apagar nada do cliente, o pedido reenvia o typeName, o guid, os attributes, os contacts e os labels tal como o GET os devolveu e junta os quatro atributos do BeryX aos customAttributes que já lá estavam (update_payload). Classificações, relações e business attributes não vão no pedido. Quando os quatro valores já são os do scan, não há escrita. O pedido não leva controlo de concorrência: uma edição feita no Purview entre o GET e o POST do mesmo push é reescrita com os valores lidos no GET.

O login no Entra ID tem um cliente HTTP próprio, com o mesmo guard anti-SSRF e IP fixado que o endpoint do Purview (CatalogSpec.auth_url). O token de acesso é pedido uma vez por push e fica só em memória; o client secret e o token nunca aparecem em mensagens nem em logs.

Setup

  1. Service principal: registar uma app no Entra ID, criar-lhe um client secret e, no Data Map do Purview, dar-lhe a role Data Curator na coleção onde estão as tabelas (a role que lê e altera assets).

  2. Ligar: Conexões → Catálogo externo → Ligar um catálogo → Microsoft Purview:

    • Endpoint da conta Purview: https://<conta>.purview.azure.com (aceita também …/datamap/api);
    • Tenant (Directory ID) do Entra ID: o GUID do diretório ou um domínio verificado (empresa.onmicrosoft.com);
    • Client ID da app registada: o GUID da app;
    • Client secret: cifrado com Fernet, nunca volta a ser mostrado.

    O tenant e o client ID não são segredos e ficam em claro em catalog_integrations.settings_json (sem migration: a coluna existe desde o Collibra). Ligar e testar pede um token ao Entra ID e lê a definição do tipo DataSet no Data Map: confirma as credenciais e a leitura. A permissão de escrita só se confirma no primeiro push.

  3. Mapear: o prefixo é o qualifiedName da base no Purview; o BeryX acrescenta /schema/tabela e procura a entidade pelo tipo e pelo qualifiedName. O tipo (typeName) deduz-se do host onde a especificação o mostra; nas outras fontes escreve-se «tipo:qualifiedName»:

    Fonte Prefixo typeName
    Azure SQL Database mssql://<servidor>.database.windows.net/<base> azure_sql_table, deduzido
    Azure SQL Managed Instance mssql://<host>.database.windows.net:3342/<base> azure_sql_mi_table, deduzido da porta 3342
    Synapse, pool dedicado do workspace mssql://<workspace>.sql.azuresynapse.net/<pool> azure_synapse_dedicated_sql_table, deduzido
    Pool dedicado autónomo (ex-SQL DW) azure_sql_dw_table:mssql://<servidor>.database.windows.net/<dw> explícito: o host é igual ao do Azure SQL Database
    Synapse serverless, SQL Server, Fabric e outros <typeName>:<qualifiedName> explícito

    No Fabric o qualifiedName de uma tabela de Lakehouse acaba em …/tables/dbo%252Fminha_tabela (o schema e a tabela vão juntos, com a barra codificada), e por isso não se forma com prefixo + /schema/tabela: usa-se uma exceção por dataset com o qualifiedName completo copiado do Purview. As exceções aceitam a mesma forma [tipo:]qualifiedName. Em produção, o conector Fabric não vem na imagem gerida (ver as notas honestas em CONECTORES.md); as fontes Microsoft que chegam ao Purview por este caminho são o Azure SQL e o Synapse, pelo conector mssql.

Comportamento em falha

  • Entidade não encontrada (404 do GET, ou resposta sem entidade): o dataset fica em «sem tabela no catálogo» com a referência tentada («tipo:qualifiedName»). Um tipo errado aparece aqui.
  • 401 do Entra ID (secret errado ou expirado) ou do Data Map (token recusado): o push fica falhou com «Entra ID devolveu 401: …» ou «Microsoft Purview devolveu 401: …», sem segredo nem token. O log catalog_push_dataset_failed leva o correlation_id do scan; três falhas seguidas sem nenhum sucesso param o push.
  • 429 e 5xx: duas tentativas extra com espera curta, como nos outros catálogos.
  • Como nos outros catálogos, nenhum erro do Purview falha o scan.
  • Ler do catálogo (cartão #140) ainda não é suportado no Purview: a opção fica escondida e POST /connections/{id}/catalog-import/plan responde

Fora desta fase

  • Classificação «BeryX verdict»: exige criar a definição de tipo da classificação e aplicá-la à entidade; fica para um cartão seguinte.
  • Data Quality API do Unified Catalog: segundo a página da Microsoft (learn.microsoft.com/rest/api/purview/unified-catalog-data-quality), está em pré-visualização pública desde dezembro de 2025 e só cobre as funcionalidades GA. Publicar lá as regras fica para quando sair da pré-visualização.
  • Clouds soberanas (Azure Government, Azure China): o login usa sempre login.microsoftonline.com e o scope https://purview.azure.net/.default.

Por confirmar no tenant (Purview)

  1. Entidade inexistente: o Apache Atlas responde 404 com ATLAS-404-00-009; a especificação do Purview só documenta o corpo de erro genérico. O cliente trata o 404 e um 200 sem entidade como «não encontrada».
  2. Reenvio dos atributos lidos: o createOrUpdate aceita os attributes, contacts e labels tal como o GET os devolve, sem recusar atributos só de leitura e sem duplicar contactos ou labels.
  3. Tipos deduzidos: azure_sql_table, azure_sql_mi_table e azure_sql_dw_table vêm dos exemplos da especificação (Discovery_Query_*); azure_synapse_dedicated_sql_table vem do acelerador oficial de linhagem da Microsoft (Purview-ADB-Lineage-Solution-Accelerator), não do scanner.
  4. Limites dos customAttributes: no Apache Atlas, chave até 50 caracteres ([a-zA-Z0-9_-]) e valor até 500, por omissão; a documentação do Purview não publica limites. O BeryX corta cada valor a 500 caracteres.

Ler do catálogo (cartão #140)

Clientes com OpenMetadata ou DataHub (o Collibra e o Purview ainda não — ver acima) já curaram owners, domínios, tags (PII, Sensitive…) e glossário. Em vez de os recriar à mão, o BeryX lê essa curadoria pela mesma integração e pelo mesmo mapeamento dataset → FQN/URN da conexão (prefixo + exceções). O catálogo nunca é escrito neste caminho:

Catálogo Pedidos (só leitura)
OpenMetadata GET /api/v1/tables/name/{fqn}?fields=owners,domain,tags,columns · GET /api/v1/tables?database=… (listar)
DataHub POST /api/graphql só com query — dataset(urn){ownership, domain, tags, glossaryTerms, schemaMetadata…} e search (listar)

O cliente de leitura (ReadOnlyJsonHttp) recusa, antes de sair para a rede, qualquer método que não seja GET/HEAD e, no DataHub, qualquer POST que não seja uma query GraphQL (uma mutation é recusada). No OpenMetadata os termos de glossário vêm nas tags com source=Glossary.

O que é importado

Do catálogo No BeryX Regras
Domínio da tabela Domínio (criado se não existir) + associação do dataset Upsert pelo nome, sem distinguir maiúsculas nem espaços a mais. Nunca remove associações.
Owners (utilizadores) Owner do domínio Só se o domínio ainda não tiver owner e o email/username do catálogo corresponder a uma conta ativa do workspace. Sem correspondência → aviso (sem criar contas nem convites). Equipas/grupos são ignorados.
Tags das colunas Nível de sensibilidade com origem catálogo Ver tabela abaixo. Nunca sobrepõe uma classificação manual.
Descrição da tabela Dataset.description (docs_source = catalog) Só quando a descrição do BeryX está vazia.
Termos de glossário — Só contados; não entram na base de conhecimento nesta fase.

Tags → nível de sensibilidade (último segmento da tag, sem maiúsculas; o nível mais alto ganha quando há várias):

Tag no catálogo Nível
PII, qualquer PII.* (PII.Sensitive, PII.NonSensitive) Dados pessoais
Sensitive, Confidential Confidencial
Internal Interno
Public Público

Precedência: manual > catálogo > automático. O import cria a classificação se a coluna não tiver nenhuma, atualiza uma que já veio do catálogo, e só sobe uma automática (nunca desclassifica PII detetado). A deteção de PII dos scans continua a poder subir uma classificação do catálogo para «Dados pessoais». Cada mudança fica no rasto da coluna (origem catalog, nota com a tag). Tags só ao nível da tabela não classificam colunas — ficam como aviso no plano.

Plano e aplicação

  1. Conexões → Catálogo externo → Ler do catálogo → Pré-visualizar import: o plano lista o que muda (+ criar, ~ alterar), os avisos (owners sem conta, curadoria manual mantida, tabelas com erro) e as contagens.
  2. Aplicar import volta a ler o catálogo e aplica numa transação. Um segundo apply dá 0 alterações (idempotente).
  3. Opção «Importar do catálogo ao sincronizar»: o import corre no fim de cada scan concluído, depois do push dos verdicts, numa transação própria — best-effort, nunca falha o scan.

Em falha: cada tabela é lida à parte — uma tabela com erro fica em aviso e o lote continua; tabela inexistente no catálogo (404) conta como «sem metadados». Três falhas seguidas sem nenhuma leitura bem-sucedida param a leitura (catálogo em baixo ou token revogado).

Privacidade: emails/usernames dos owners do catálogo são dados pessoais — só servem para procurar a conta do workspace; não vão para logs, nem para a auditoria, nem para a resposta do plano (que mostra o nome da conta do BeryX). O token nunca aparece em mensagens.

API

Método Caminho Quem Efeito
POST /connections/{id}/catalog-import/plan admin Dry-run: {changes, warnings, errors, summary, stats, text}
POST /connections/{id}/catalog-import/apply admin Aplica; auditoria catalog_import_applied (só contagens)
PUT /connections/{id}/catalog-sync admin Campo import_on_sync (omitido = mantém)

O estado da conexão (GET /connections/{id}/catalog-sync) inclui import_on_sync, last_import_at e last_import_stats (tables, read, not_found, failed, skipped, changes…).

Permissões no catálogo: o bot/token só precisa de leitura de tabelas (OpenMetadata) ou de ver datasets (DataHub) para o import — as permissões de escrita de testes/assertions só são precisas para publicar.