PROYECTOS PÚBLICOS

Proyectos

Selección de proyectos públicos en los que desarrollo soluciones de Data Governance, automatización y arquitectura de datos. Cada caso resume el problema que aborda, el enfoque seguido y las decisiones principales, con el repositorio disponible para revisar la implementación en detalle.

collibra-governance-automation

v1.2.0

Collibra Governance Automation

Automatiza el paso desde metadatos técnicos procedentes de varias fuentes hasta un modelo de gobierno común que puede revisarse, analizarse y sincronizarse con Collibra de forma controlada.

Qué problema resuelve

PostgreSQL, ODCS, dbt y OpenLineage describen partes distintas del mismo ecosistema. El problema no es simplemente reunir esos metadatos, sino darles una identidad común, conservar de dónde proceden y entender cómo se relacionan antes de llevarlos a una plataforma de gobierno.

Cómo lo he planteado

El proyecto construye primero un modelo de gobierno neutral e independiente de Collibra. Sobre ese modelo se pueden comprobar reglas, analizar el impacto de los cambios y preparar acciones revisables. Collibra queda al final del flujo como destino de sincronización, no como la fuente de verdad del modelo.

Ver cómo funciona el proyecto

Cómo funciona el proyecto

Este proyecto automatiza dos recorridos distintos que comparten principios de gobierno, revisión y determinismo, pero no el mismo modelo interno. El primero parte de PostgreSQL, construye un GovernanceModel y controla qué cambios pueden prepararse y sincronizarse con Collibra. El segundo compone ODCS, dbt y OpenLineage en un GovernanceGraph para conservar procedencia, construir linaje y analizar qué activos pueden verse afectados por un cambio.

Separar ambos recorridos es una decisión importante de la arquitectura actual: PostgreSQL no alimenta el grafo de impacto y el grafo multi-source no alimenta la sincronización con Collibra. El portfolio debe mostrar esa separación tal como existe en el código, sin convertirla en un único pipeline que hoy no existe.

POSTGRESQL → GOVERNANCEMODEL → COLLIBRA

ODCS + DBT + OPENLINEAGE → GOVERNANCEGRAPH → IMPACTO

Dos recorridos, dos modelos

GovernanceModel y GovernanceGraph son dos núcleos vendor-neutral diferentes. GovernanceModel representa la metadata física descubierta en PostgreSQL y es la base del camino de políticas y sincronización con Collibra. GovernanceGraph representa nodos, relaciones y procedencia procedentes de ODCS, dbt y OpenLineage y es la base del análisis de impacto.

No existe actualmente una conversión GovernanceModel → GovernanceGraph. Esta separación evita atribuir al proyecto una integración end-to-end que todavía no está implementada y permite explicar con precisión qué problema resuelve cada recorrido.

ROOT

CONTROL Y SINCRONIZACIÓN

GovernanceModel

CONTEXTO E IMPACTO

GovernanceGraph

RECORRIDO A

Control y sincronización con Collibra

Este recorrido responde a una pregunta operativa: qué metadata física existe en PostgreSQL, si cumple unas comprobaciones básicas de gobierno y qué cambios habría que preparar para que el estado gestionado de Collibra la represente sin aplicar escrituras por defecto.

EJEMPLO EN CURSO · commerce.orders

A1

Descubrimiento de PostgreSQL

El recorrido empieza observando directamente los catálogos de PostgreSQL. El scanner trabaja en una transacción REPEATABLE READ y READ ONLY para obtener una fotografía consistente de la estructura sin modificar la base de datos.

QUÉ ENTRA

Una conexión PostgreSQL y los catálogos del database configurado.

QUÉ HACE PYTHON

Python ejecuta cinco consultas de catálogo y reconstruye databases, schemas de usuario, tablas, columnas, tipos, nullability, primary keys, foreign keys, comentarios y ownership. Las views, los índices y las CHECK constraints no forman parte del discovery implementado actualmente.

RESULTADO

Un GovernanceModel con una jerarquía Data Source → Database → Schema → Table → Column y relaciones estructurales derivadas de las foreign keys.

EVIDENCIA EN CÓDIGO

PostgresMetadataScanner.scan · build_governance_model

commerce

orders

  • order_id

  • customer_id

orders.customer_idcustomers.customer_id

En la demo commerce, Python observa la tabla orders y la foreign key orders.customer_id → customers.customer_id. La relación se conserva dentro del GovernanceModel como metadata estructural.

A2

Modelo e identidades estables

La metadata descubierta no se conserva como filas sueltas de catálogo. Python la convierte en objetos de dominio con identidades estables para que el mismo activo pueda reconocerse de forma reproducible entre ejecuciones.

QUÉ ENTRA

Las filas normalizadas obtenidas por el scanner de PostgreSQL.

QUÉ HACE PYTHON

Python construye IDs canónicos para cada nivel del modelo, valida la integridad de las referencias y ordena las colecciones de forma determinista. El host y el puerto de PostgreSQL no forman parte de la identidad de tablas y columnas, por lo que mover la conexión no cambia por sí solo la identidad lógica del activo.

RESULTADO

Un GovernanceModel vendor-neutral, estable y revisable que puede utilizarse sin depender todavía de Collibra.

EVIDENCIA EN CÓDIGO

GovernanceModel · make_table_id · make_column_id · make_relationship_id

  1. RAW CATALOG ROWS

  2. CANONICAL IDS

  3. GOVERNANCEMODEL

La tabla del ejemplo queda identificada como tbl:governance-demo/governance_demo/commerce/orders y la columna customer_id como col:governance-demo/governance_demo/commerce/orders/customer_id.

A3

Comprobaciones de gobierno

Antes de preparar cambios hacia Collibra, el proyecto puede aplicar un conjunto pequeño y explícito de reglas sobre el GovernanceModel. No es un motor genérico de políticas: actualmente existen tres tipos de comprobación definidos por el proyecto.

QUÉ ENTRA

El GovernanceModel y las reglas declaradas en la configuración Governance-as-Code.

QUÉ HACE PYTHON

Python evalúa si los activos seleccionados tienen owner, descripción y relaciones cuando las reglas require_owner, require_description o require_relationship lo exigen. Las violaciones se ordenan y se reportan; una violación con severidad de error puede bloquear check o la generación del plan.

RESULTADO

Un informe de violaciones que permite separar problemas de gobierno de la fase de sincronización.

EVIDENCIA EN CÓDIGO

evaluate_policies · NormalizedPolicySet

GovernanceModel

  • require_owner · exige ownership

  • require_description · exige descripción

  • require_relationship · exige al menos una relación

report

A4

Estado deseado y plan revisable

Collibra aparece al final del modelo, no al principio. Python traduce el GovernanceModel neutral a una representación específica de Collibra y compara ese estado deseado con el estado remoto gestionado antes de decidir qué operaciones serían necesarias.

QUÉ ENTRA

GovernanceModel + mapping de Collibra + estado remoto gestionado.

QUÉ HACE PYTHON

Python transforma databases, schemas, tablas, columnas y relaciones FK en CollibraAssetSpec y CollibraRelationshipSpec, incluyendo referencias de dominio, tipos y atributos configurados. Después calcula un SyncPlan con CREATE, UPDATE, UNCHANGED y REMOTE_ONLY, y puede guardar las acciones en un .gplan junto con identidades de configuración, snapshot, políticas, mapping, target context y remote state.

RESULTADO

Un plan revisable que combina una lista ordenada de operaciones con un contrato de integridad. REMOTE_ONLY se reporta, pero no se convierte en una operación de borrado.

El .gplan no es solo una descripción: conserva las acciones y las identidades necesarias para detectar si el contexto ha cambiado antes de aplicar.

EVIDENCIA EN CÓDIGO

map_to_desired_state · build_sync_plan · build_saved_plan · SavedGovernancePlan

  1. 01

    GovernanceModel

  2. 02

    CollibraDesiredState

    + managed remote

  3. 03

    SyncPlan

  4. 04

    .gplan

  • CREATE

  • UPDATE

  • UNCHANGED

El .gplan no es solo una descripción: conserva las acciones y las identidades necesarias para detectar si el contexto ha cambiado antes de aplicar.

A5

Sincronización segura

Tener un plan no autoriza una escritura. El flujo mantiene dry-run como comportamiento por defecto, exige opt-in explícito para aplicar y añade comprobaciones adicionales antes de permitir operaciones contra un adapter real.

QUÉ ENTRA

Un SyncPlan o .gplan revisado, la configuración actual y un adapter Collibra mock o live.

QUÉ HACE PYTHON

Python ejecuta dry-run sin escrituras por defecto. Para aplicar es necesario habilitar --apply y, si el adapter es live, confirmar además con --confirm-live. Antes de escribir, el flujo de .gplan comprueba que las identidades relevantes sigan coincidiendo; si el plan está stale, se bloquea antes de la primera escritura. Durante apply, los errores de escritura detienen la secuencia.

RESULTADO

CREATE y UPDATE pueden ejecutarse cuando se solicita explícitamente. El proyecto no implementa DELETE, borrado automático, rollback ni un motor de retries demostrado.

El LiveCollibraAdapter está contract-tested contra HTTP simulado. El repositorio no demuestra validación contra un tenant comercial real de Collibra.

EVIDENCIA EN CÓDIGO

execute_sync_plan · plans/stale.py · MockCollibraAdapter · LiveCollibraAdapter

.gplan

DRY-RUN · DEFAULT

--apply ?

NO → 0 WRITES

YES

LIVE ADAPTER ?

NO → continue

YES → --confirm-live

STALE ?

NO → CREATE / UPDATE

RESULT

En el lifecycle local con MockCollibraAdapter, un remoto vacío produce creaciones y una segunda sincronización contra el nuevo estado no vuelve a crear los mismos activos.

El LiveCollibraAdapter está contract-tested contra HTTP simulado. El repositorio no demuestra validación contra un tenant comercial real de Collibra.

Collibra no tiene un único fixture que una PostgreSQL, ODCS, dbt y OpenLineage en una ejecución end-to-end. El recorrido PostgreSQL → Collibra y el recorrido ODCS/dbt/OpenLineage → impacto se muestran con ejemplos reales diferentes para no atribuir al proyecto una integración que todavía no existe.

RECORRIDO B

Contexto, linaje e impacto

Este recorrido responde a otra pregunta: si cambia un activo, qué dependencias, contratos y consumidores quedan dentro de su radio de impacto. Para responderla, Python compone metadata declarada, transformacional y observada procedente de ODCS, dbt y OpenLineage.

EJEMPLO EN CURSO · orders → downstream

B1

Fuentes de contexto

Las tres fuentes no aportan lo mismo. ODCS describe contratos y contexto declarado, dbt describe modelos y dependencias de transformación y OpenLineage aporta observaciones de ejecución y linaje. El valor aparece al conservar esas diferencias en lugar de reducirlas a un único formato sin procedencia.

QUÉ ENTRA

Documentos ODCS v3.1.0, un subset de dbt Manifest v12 y eventos OpenLineage core 2-0-2.

QUÉ HACE PYTHON

Python valida y mapea cada fuente de forma específica. ODCS crea nodos contract, dataset y column con relaciones governs y contains. dbt convierte models, sources, columns y parent_map en estructura física y relaciones depends_on. OpenLineage compone RunEvent, JobEvent y DatasetEvent, datasets de entrada y salida y, cuando existe, columnLineage.

RESULTADO

Tres conjuntos de nodos, relaciones y procedencia preparados para componerse en un GovernanceGraph.

ODCS puede expresar quality, SLA y servers en el standard, pero este proyecto no los mapea actualmente al GovernanceGraph.

EVIDENCIA EN CÓDIGO

load_odcs_graph · load_dbt_graph · load_openlineage_graph

  • ODCS · contrato y contexto declarado

    contract → governs → dataset → contains → column

  • dbt · modelos y dependencias declaradas

    source/model → depends_on

  • OpenLineage · ejecución observada y column lineage

    input → run/job → output

    + columnLineage

ODCS puede expresar quality, SLA y servers en el standard, pero este proyecto no los mapea actualmente al GovernanceGraph.

B2

Identidad y procedencia

Para componer varias fuentes, el proyecto necesita decidir cuándo dos observaciones pueden representar el mismo activo y conservar de dónde procedió cada hecho. Esa unión no se basa en elegir silenciosamente una fuente ganadora.

QUÉ ENTRA

Nodos y relaciones producidos por los mappers de ODCS, dbt y OpenLineage.

QUÉ HACE PYTHON

Python construye GraphNodeIdentity con namespace, kind, logical_id y, cuando corresponde, parent. Las observaciones con la misma identidad y el mismo payload material pueden fusionar su ProvenanceRecord. Si dos observaciones con la misma identidad contienen atributos materiales incompatibles, la composición falla en lugar de escoger una fuente de forma arbitraria.

RESULTADO

Activos con identidad canónica y procedencia declarada, observada o derivada, preparados para formar parte del mismo grafo cuando sus identidades son compatibles.

dbt y OpenLineage pueden converger en la misma identidad física cuando coinciden namespace, database, schema y table.

ODCS solo converge automáticamente con otros activos si sus logical IDs han sido alineados. PostgreSQL no participa en este esquema de identidad porque pertenece al recorrido GovernanceModel.

El proyecto conserva procedencia, pero todavía no implementa un motor de authority o conflict resolution. Un conflicto material se rechaza.

EVIDENCIA EN CÓDIGO

GraphNodeIdentity · ProvenanceRecord · GovernanceGraph.from_parts

dbt observation

OpenLineage observation

SAME IDENTITY

ONE NODE

TWO PROVENANCE RECORDS

dbt y OpenLineage pueden converger en la misma identidad física cuando coinciden namespace, database, schema y table.

ODCS solo converge automáticamente con otros activos si sus logical IDs han sido alineados. PostgreSQL no participa en este esquema de identidad porque pertenece al recorrido GovernanceModel.

El proyecto conserva procedencia, pero todavía no implementa un motor de authority o conflict resolution. Un conflicto material se rechaza.

B3

GovernanceGraph

La composición produce un grafo de gobierno in-memory formado por dataclasses inmutables. No utiliza una graph database ni NetworkX: el propio dominio define cómo se normalizan, validan y ordenan nodos y relaciones.

QUÉ ENTRA

Los nodos, relaciones e información de procedencia ya normalizados por cada integración.

QUÉ HACE PYTHON

Python fusiona observaciones compatibles, comprueba que los parents existan, rechaza dangling edges, canonicaliza atributos y ordena nodos y relaciones. El grafo utiliza contains para jerarquía, depends_on para dependencias y governs para asociar contratos con los activos que gobiernan.

RESULTADO

Un GovernanceGraph determinista con content identity propia y suficiente estructura para construir linaje y recorrer dependencias.

depends_on se almacena como derived → dependency. Para calcular impacto downstream, el recorrido utiliza esa relación en sentido inverso.

EVIDENCIA EN CÓDIGO

GovernanceGraph · GraphNode · GraphEdge · canonical_json_bytes

GovernanceGraph

in-memory

  • contains

  • depends_on

  • governs

depends_on se almacena como derived → dependency. Para calcular impacto downstream, el recorrido utiliza esa relación en sentido inverso.

B4

Linaje y contratos

Dentro del grafo, las dependencias pueden proceder de fuentes diferentes y conservar distinto nivel de detalle. dbt aporta dependencias declaradas entre modelos y sources; OpenLineage aporta dependencias observadas en ejecución y puede materializar linaje entre columnas; ODCS aporta contratos asociados a datasets.

QUÉ ENTRA

parent_map de dbt, inputs/outputs y columnLineage de OpenLineage y relaciones governs de ODCS.

QUÉ HACE PYTHON

Python materializa relaciones depends_on con dirección derived → dependency. En dbt esas relaciones son de nivel table o transformation. En OpenLineage también pueden existir entre columnas mediante ColumnLineageAssertion. Los contratos ODCS permanecen como nodos contract conectados mediante governs y se incorporan como contexto del impacto.

RESULTADO

Un grafo capaz de representar dependencias dataset-level y column-level junto con el contexto contractual disponible.

dbt no genera column-level lineage en este proyecto. Esa capacidad está demostrada mediante OpenLineage.

Los contratos ODCS son contexto informativo dentro del análisis de impacto; actualmente no bloquean cambios ni sustituyen las reglas require_* del recorrido PostgreSQL.

EVIDENCIA EN CÓDIGO

materialize_column_lineage_edges · ColumnLineageAssertion · GraphEdge

  • DATASETdownstreamorders
  • COLUMNoutput columninput column
  • CONTRACTcontractdataset

dbt no genera column-level lineage en este proyecto. Esa capacidad está demostrada mediante OpenLineage.

Los contratos ODCS son contexto informativo dentro del análisis de impacto; actualmente no bloquean cambios ni sustituyen las reglas require_* del recorrido PostgreSQL.

Los tests demuestran que una identidad física construida desde OpenLineage puede ser compatible con el activo físico equivalente de dbt y que el linaje de columnas se materializa como output column → depends_on → input column.

B5

Análisis de impacto

Cuando se declara un activo modificado, el proyecto utiliza el GovernanceGraph para calcular qué consumidores quedan aguas abajo. El análisis es completamente read-only y no ejecuta políticas ni realiza escrituras remotas.

QUÉ ENTRA

GovernanceGraph + uno o varios changed roots definidos mediante governance-impact-changes/v1.

QUÉ HACE PYTHON

Python valida los roots, construye una adjacency efectiva, recorre depends_on en sentido inverso y ejecuta un BFS multi-source por distancia. Distingue impacto directo y transitivo, evita bucles sobre los roots, selecciona un camino mínimo canónico cuando existen rutas equivalentes y recoge relaciones, contratos y contexto de gobierno dentro del closure afectado.

RESULTADO

Un governance-impact-result/v1 determinista con los activos afectados, sus distancias, caminos y contexto relevante. El comando governance impact devuelve un estado impacted cuando encuentra consumidores afectados y no realiza ninguna mutación remota.

El ejemplo CLI principal es dataset-level. El column-level lineage está demostrado por tests específicos de OpenLineage y debe mostrarse como evidencia técnica complementaria, no como si formara parte del mismo fixture CLI.

EVIDENCIA EN CÓDIGO

analyze_downstream_impact · GovernanceImpactResult · _path_sort_key

orders

↓ reverse traversal over depends_on

downstream

DIRECT · distance 1

TRANSITIVE · distance ≥2

READ ONLY0 REMOTE WRITES

En el fixture real utilizado por governance impact, orders es el changed root y downstream aparece como consumidor afectado. Ese recorrido está probado por CLI y por la GitHub Action read-only.

El ejemplo CLI principal es dataset-level. El column-level lineage está demostrado por tests específicos de OpenLineage y debe mostrarse como evidencia técnica complementaria, no como si formara parte del mismo fixture CLI.

Qué hemos conseguido automatizar con Python

Python no actúa aquí como una única cadena de scripts. En el recorrido operativo descubre metadata de PostgreSQL, construye identidades estables, evalúa comprobaciones, traduce el modelo a Collibra y prepara planes revisables con dry-run y protección frente a planes obsoletos. En el recorrido de impacto ingiere ODCS, dbt y OpenLineage, compone identidades y procedencia, materializa linaje y recorre el GovernanceGraph para calcular impacto downstream de forma determinista.

  1. DESCUBRIRPostgresMetadataScanner.scan
  2. IDENTIFICARGovernanceModel
  3. COMPROBARevaluate_policies
  4. MAPEARmap_to_desired_state
  5. PLANIFICARbuild_saved_plan
  6. PROTEGERexecute_sync_plan
  7. COMPONERGovernanceGraph.from_parts
  8. TRAZAR LINAJEmaterialize_column_lineage_edges
  9. CALCULAR IMPACTOanalyze_downstream_impact
  10. EVIDENCIARContentIdentity

Identidades, ordenación, artefactos y caminos de impacto se canonicalizan para que una misma entrada produzca una representación revisable y reproducible.

Arquitectura completa

COLLIBRA GOVERNANCE AUTOMATION

DOS MODELOS · SIN CONVERSIÓN DIRECTA ACTUAL

  1. POSTGRESQL

  2. GOVERNANCEMODEL

  3. CHECKSCOLLIBRA DESIRED STATE
  4. SYNCPLAN / .GPLAN

  5. DRY-RUN

  6. APPLY

  7. COLLIBRA

  1. ODCSDBTOPENLINEAGE
  2. GOVERNANCEGRAPH

  3. PROVENANCELINEAGECONTRACTSIMPACT ANALYSIS
  4. IMPACT RESULT

  5. PR / REVIEW

Madurez y evolución

El polígono refleja el estado funcional documentado. El anillo exterior representa el perfil completo.

  • Lo más consolidado

    El discovery read-only de PostgreSQL, el GovernanceModel, la composición ODCS/dbt/OpenLineage, el GovernanceGraph, el column-level lineage mediante OpenLineage, el análisis de impacto determinista y la planificación segura hacia Collibra forman capacidades demostradas por código y tests.

  • Lo que está evolucionando

    La integración live de Collibra está contract-tested, pero no validada contra un tenant comercial real. PostgreSQL y el GovernanceGraph siguen siendo recorridos separados, y el proyecto todavía no implementa un motor de authority o resolución de conflictos entre fuentes.

  • Siguientes áreas

    El repositorio documenta como áreas pendientes el hardening de la integración con Collibra, la gestión de authority, conflictos y drift y una mayor extensibilidad de providers. Se presentan como evolución futura, no como capacidades implementadas ni como un roadmap versionado cerrado.

Madurez y evolución

  1. ACTUAL · v1.2.0
  2. ÁREAS SIGUIENTESCollibra hardeningFUTURE
  3. ÁREAS SIGUIENTESAuthority / conflicts / driftFUTURE
  4. ÁREAS SIGUIENTESProvider extensibilityFUTURE

Qué puedes revisar en GitHub

El repositorio permite comprobar por separado el discovery y la sincronización con Collibra, la composición multi-source del GovernanceGraph, el linaje, el análisis de impacto y los controles de seguridad de los planes.

purview-governance-automation

v1.1.0

Microsoft Purview Governance Automation

Automatiza la configuración de Microsoft Purview como un estado deseado revisable: observa el entorno real, detecta diferencias, prepara un plan y solo ejecuta los cambios que superan las comprobaciones de seguridad.

Qué problema resuelve

Cuando la configuración de Purview se mantiene mediante operaciones manuales o scripts directos, resulta difícil saber qué debería existir, qué ha cambiado realmente y qué se va a modificar en cada ejecución.

Cómo lo he planteado

El proyecto parte de una configuración deseada, observa el estado real de Purview, clasifica las diferencias y genera un plan determinista. Antes de escribir vuelve a consultar el entorno y bloquea la ejecución si el estado ya no coincide con el contexto para el que se creó el plan.

Ver cómo funciona el proyecto

Cómo funciona el proyecto

Este proyecto convierte la configuración de Microsoft Purview Scanning en un proceso declarativo, revisable y seguro. Python valida cómo debería quedar el entorno, observa cómo está realmente, calcula las diferencias, prepara un plan ejecutable y vuelve a comprobar el estado remoto justo antes de cualquier escritura. El objetivo no es automatizar cambios a ciegas, sino hacer que cada decisión sea explícita, reproducible y auditable.

  1. CONFIGURACIÓN
  2. VALIDACIÓN
  3. ESTADO REAL
  4. COMPARACIÓN
  5. PLAN
  6. EJECUCIÓN SEGURA
  7. RESULTADO

El ejemplo que recorre estas siete capas se reproduce contra el contract server offline del repositorio. Demuestra el comportamiento del pipeline y sus contratos, pero no constituye una validación contra un tenant real de Microsoft Purview.

01

Configuración deseada

El punto de partida es un documento versionado que describe cómo queremos que quede configurado Purview. No contiene credenciales ni presupone que esos recursos ya existan: expresa una intención que el resto del flujo debe validar, comparar y, si corresponde, ejecutar.

QUÉ ENTRA

Un archivo YAML o JSON con el target de Purview y los recursos que queremos gestionar. En la versión v2 el proyecto soporta Azure Storage Data Sources, Custom Classification Rules, Custom Azure Storage Scan Rule Sets y AzureStorageMsi Scans.

QUÉ HACE PYTHON

Python carga el YAML o JSON mediante parsing seguro y estricto, detecta claves duplicadas e identifica la versión del contrato declarada por el documento. En este punto todavía no consulta Purview ni decide qué cambios realizar: convierte la declaración de entrada en una estructura que puede pasar por las siguientes comprobaciones.

RESULTADO

Un documento de configuración deseada parseado y versionado, listo para pasar por validación y normalización.

EVIDENCIA EN CÓDIGO

load_config_file · purview-governance-config/v1|v2

ds-a

custom-rule

custom-srs

DailyScan @ ds-a

(ds-a, DailyScan)

ds-b

DailyScan @ ds-b

(ds-b, DailyScan)

Dos scans pueden compartir el mismo nombre sin representar el mismo recurso. El proyecto identifica cada scan mediante la combinación del Data Source padre y su nombre: (dataSourceName, name).

02

Validación y normalización

Antes de comparar nada con Purview, el proyecto comprueba que la configuración tenga una forma válida y después la convierte en una representación canónica. Validar y normalizar son responsabilidades distintas: la validación decide si el documento es aceptable; la normalización elimina diferencias de representación que no deberían cambiar su significado.

QUÉ ENTRA

El documento ya parseado, sus schemas versionados y los recursos declarados por el usuario.

QUÉ HACE PYTHON

Python valida el documento con JSON Schema, rechaza propiedades desconocidas o sensibles, comprueba tipos e identidades duplicadas y exige un endpoint HTTPS válido. Después canonicaliza el endpoint, ordena recursos y listas, normaliza valores numéricos finitos y construye una GovernanceConfig tipada e inmutable. Cuando se crea el plan, desired_state_from_config proyecta desde esa configuración únicamente los campos materiales que realmente participarán en la comparación.

RESULTADO

Una GovernanceConfig canónica y determinista y, durante la planificación, un DesiredState que representa únicamente la parte material de esa intención. Dos documentos equivalentes en significado pueden converger en la misma representación aunque su orden original sea distinto.

EVIDENCIA EN CÓDIGO

validate_document · normalize_document · GovernanceConfig · desired_state_from_config · DesiredState

INPUT

  • https://a.blob.core.windows.net/
  • [CSV, JSON]
  • 80.0
  • DailyScan @ ds-a

CANONICAL

  • canonical endpoint
  • sorted lists
  • normalized finite double
  • stable identity

La normalización no cambia la intención. Hace que el sistema compare significado y no diferencias accidentales de formato u orden.

03

Observación del estado real

La configuración deseada solo explica cómo queremos que quede el entorno. Para saber si existe algo que cambiar, Python necesita observar cómo está configurado Purview en ese momento y convertir esa lectura a una representación comparable.

QUÉ ENTRA

Un cliente autenticado contra Microsoft Purview Scanning Data Plane y las respuestas LIST/GET de la API 2023-09-01.

QUÉ HACE PYTHON

Python descubre los recursos remotos, ordena sus identidades, obtiene el detalle necesario, rechaza shapes inseguros o sensibles y normaliza cada recurso soportado. Después construye un RemoteStateV2 y calcula una materialStateIdentity mediante SHA-256 sobre una representación canónica del estado material.

RESULTADO

Un snapshot remoto versionado que describe qué existe realmente y una identidad estable que permite comprobar más adelante si ese estado ha cambiado.

La captura manual remote-state capture sirve para auditoría. plan create no reutiliza ese archivo: realiza su propia captura fresca antes de calcular diferencias.

EVIDENCIA EN CÓDIGO

capture_remote_state_v2 · compute_material_state_identity · PurviewScanningClient

DESIRED

6 resources

REMOTE

0 resources

RemoteStateV2

materialStateIdentity = sha256:…

04

Comparación

Con el estado deseado y el estado remoto ya normalizados, Python empareja cada recurso por su identidad y clasifica la diferencia. Esta etapa todavía es de solo lectura: decide qué significa cada discrepancia, pero no ejecuta ningún cambio.

QUÉ ENTRA

DesiredState + RemoteStateV2.

QUÉ HACE PYTHON

Python empareja Data Sources, Classification Rules y Scan Rule Sets por nombre, y los Scans por la identidad compuesta (dataSourceName, name). Después compara únicamente los campos materiales, aplica reglas de seguridad y produce outcomes y razones ordenados de forma determinista.

RESULTADO

Un DiffDocument con un outcome y sus razones para cada recurso. Ese documento no se persiste como artefacto independiente: pasa a formar parte del changeSet del plan.

EVIDENCIA EN CÓDIGO

diff_desired_vs_remote · DiffDocument

DiffDocument

  • CREATE

    Está en la configuración deseada y no existe en Purview. Puede convertirse en una operación de creación.

  • REPLACE

    Existe en ambos lados, pero hay una diferencia material que el proyecto considera segura de actualizar.

  • NO-OP

    La configuración relevante ya coincide. No hay nada que escribir.

  • REMOTE-ONLY

    Existe en Purview pero no forma parte del estado deseado. Se informa como diferencia, pero el proyecto no lo borra.

  • BLOCKED

    La diferencia no puede tratarse con seguridad o está fuera del contrato soportado. El plan queda bloqueado para escritura.

En el ejemplo real, los seis recursos existen en desired y ninguno existe todavía en remote. El resultado es CREATE para los seis.

05

Plan de cambios

Detectar una diferencia no autoriza una escritura. El proyecto transforma la comparación en un artefacto versionado y revisable que conserva el contexto completo, separa lo informativo de lo ejecutable y fija exactamente qué operaciones podrían llegar a realizarse.

QUÉ ENTRA

La configuración validada, el estado remoto capturado y el DiffDocument calculado a partir de ambos.

QUÉ HACE PYTHON

Python incorpora el changeSet completo, selecciona como operaciones ejecutables únicamente CREATE y REPLACE, ordena las operaciones por tipo, incrusta el desiredState que actuará como autoridad para construir los payloads y guarda las identidades del target, la configuración y el estado remoto. Finalmente calcula un planIdentity y vuelve a validar el contrato del plan.

RESULTADO

Un purview-governance-plan/v2 que funciona a la vez como explicación de las diferencias, contrato ejecutable y lista ordenada de operaciones.

EVIDENCIA EN CÓDIGO

build_governance_plan_v2 · GovernancePlan · planIdentity

  1. 01

    CREATE · dataSource · ds-a

  2. 02

    CREATE · dataSource · ds-b

  3. 03

    CREATE · classificationRule · custom-rule

  4. 04

    CREATE · scanRuleSet · custom-srs

  5. 05

    CREATE · scan · DailyScan @ ds-a

  6. 06

    CREATE · scan · DailyScan @ ds-b

El orden es determinista y respeta las dependencias del modelo: primero los Data Sources, después las reglas de clasificación, los Scan Rule Sets y, por último, los Scans.

06

Ejecución segura

Un plan no obtiene permiso de escritura solo por existir. Antes del primer PUT, Python vuelve a comprobar el contrato, el modo, la elegibilidad, el target, los payloads y el estado remoto. Si cualquiera de esas condiciones deja de ser segura, la ejecución se detiene antes de escribir.

QUÉ ENTRA

Un GovernancePlan validado, un cliente vinculado al target y un ExecutionMode que por defecto es DRY_RUN.

QUÉ HACE PYTHON

Python recorre una secuencia fail-closed de comprobaciones. Solo si todas pasan puede llegar a la frontera de escritura. El dry-run ejecuta las mismas comprobaciones previas que apply, incluida una nueva captura remota y la validación exacta de staleness, pero termina sin realizar PUT.

RESULTADO

dry-run-ready si todo es seguro y no se ha solicitado escribir; applied si se ha habilitado APPLY y las operaciones terminan correctamente; o un estado bloqueante que explica por qué no se llegó a escribir o por qué la ejecución se detuvo.

EVIDENCIA EN CÓDIGO

execute_governance_plan · materialize_mutation_intents_v2 · ExecutionMode

  1. 01Revalidar el plan

    Comprueba de nuevo la integridad de schema y semántica del GovernancePlan.

  2. 02Confirmar el modo

    Solo se aceptan los modos de ejecución definidos por ExecutionMode.

  3. 03Comprobar elegibilidad

    Si el plan está blocked, la ejecución termina con cero escrituras.

  4. 04Validar las operaciones

    Solo se admiten acciones create o replace y tipos soportados por la versión del plan.

  5. 05Vincular el target

    El endpoint y la identidad del cliente deben coincidir con el target guardado en el plan.

  6. 06Materializar los payloads

    Los cuerpos de mutación se construyen desde el desiredState embebido en el plan, no desde un estado externo que pueda haber cambiado.

  7. 07Capturar Purview de nuevo

    Python realiza una nueva lectura completa del estado remoto justo antes de la frontera de escritura.

  8. 08Comprobar que el plan sigue vigente

    La identidad del estado observado debe coincidir exactamente con la identidad remota guardada al crear el plan.

DRY-RUN

dry-run-ready · 0 PUT

APPLY

sequential PUTs

Dry-run no es una simulación superficial: recorre todos los gates previos, materializa los payloads y vuelve a leer Purview. La única diferencia es que se detiene antes de escribir.

El plan se preparó cuando el estado remoto estaba vacío. Antes de aplicar, Python vuelve a consultar Purview y detecta que ahora existe inventario remoto. Como la identidad material ya no coincide con la que quedó fijada en el plan, la ejecución completa se bloquea antes de cualquier escritura.

Esto protege contra un plan obsoleto. No es un motor completo de drift.

APPLY es opt-in. Solo permite create/replace, ejecuta las operaciones en el orden del plan y se detiene ante el primer fallo de escritura. El proyecto no implementa borrado automático, retries automáticos ni rollback.

07

Resultado y evidencia

El flujo no termina con una llamada HTTP. Python construye un resultado versionado que relaciona lo que se había planificado con lo que realmente ocurrió, de forma que una ejecución correcta, bloqueada o fallida pueda revisarse después.

QUÉ ENTRA

El plan, el modo de ejecución, las identidades observadas durante el preflight y el resultado de cada operación intentada.

QUÉ HACE PYTHON

Python registra el planIdentity, el target previsto y ejecutado, el estado remoto previsto y observado, el modo, el status global, los contadores de escritura y el estado de cada operación. Si existe un fallo, conserva también su clasificación. El contrato no añade timestamps de ejecución.

RESULTADO

Un purview-execution-result/v2 con una resultIdentity propia y suficiente contexto para distinguir qué se pretendía hacer de qué ocurrió realmente.

EVIDENCIA EN CÓDIGO

build_execution_result_v2_from_parts · ExecutionResultV2 · resultIdentity

  • DRY-RUN

    status: dry-run-ready

    writesAttempted: 0

    operations: not-run

  • APPLY

    status: applied

    writesPerformed: 6

    operations: 6 succeeded

  • Después de aplicar

    RE-PLAN

    Al volver a planificar contra el nuevo estado remoto, desired y remote ya coinciden. El plan no contiene operaciones y una nueva ejecución no intenta ninguna escritura.

Qué hemos conseguido automatizar con Python

Python no actúa aquí como un simple cliente de API. El proyecto lo utiliza para convertir una intención declarativa en un proceso reproducible: validar y normalizar configuración, proyectar el estado material que realmente importa, observar Purview, comparar recursos, construir un plan determinista, materializar payloads desde ese plan, bloquear ejecuciones que ya no representan el estado actual y registrar el resultado. La escritura queda al final del sistema y solo se habilita después de que todas esas condiciones se cumplan.

  1. VALIDARvalidate_config_file
  2. NORMALIZARnormalize_document
  3. OBSERVARcapture_remote_state_v2
  4. COMPARARdiff_desired_vs_remote
  5. PLANIFICARbuild_governance_plan_v2
  6. PROTEGERexecute_governance_plan
  7. EVIDENCIARbuild_execution_result_v2_from_parts

Recorrido completo

  1. CONFIGURACIÓN DESEADA
  2. VALIDACIÓN + NORMALIZACIÓN
  3. ESTADO REAL
  4. COMPARACIÓN
  5. PLAN
  6. CAPTURA FRESCA
  7. ¿SIGUE VIGENTE?
  8. NO →STALE · 0 WRITES
  9. YES →DRY-RUN · 0 WRITESAPPLY · CREATE/REPLACE
  10. EXECUTION RESULT

Madurez y evolución

El polígono refleja el estado funcional documentado. El anillo exterior representa el perfil completo.

  • Lo más consolidado

    La configuración deseada, la captura del estado remoto, la comparación determinista, el plan de cambios y las comprobaciones previas a ejecución forman ya un núcleo coherente y probado mediante contratos offline.

  • Lo que está evolucionando

    La cobertura actual se concentra en Scanning y Classification dentro del slice Azure Storage soportado. La validación contra un tenant real y la operación prolongada en un entorno de producción quedan fuera de las capacidades demostradas actualmente.

  • Lo siguiente

    La evolución prevista amplía el alcance hacia Unified Catalog, operaciones de drift y una mayor extensibilidad y escala empresarial, sin presentarlas todavía como capacidades implementadas.

Roadmap

  1. Actual · v1.1Scanning & Classification as CodeConfiguración, estado remoto, plan y apply para el slice AzureStorage.
  2. Siguiente · v1.2Unified Catalog GovernanceAPI Public Preview aislada del núcleo estable.FUTURE
  3. Después · v1.3Drift y operacionesDesviación (drift), retry/backoff, rate limits y telemetría.FUTURE
  4. Objetivo · v2.0Extensibilidad y escalaEscala, concurrencia y contratos de extensión.FUTURE

Qué puedes revisar en GitHub

Implementación

Permite revisar cómo se modela el estado deseado, se observa Purview y se construye el plan.

Contratos

Permite revisar las representaciones versionadas que hacen reproducible el ciclo.

Seguridad y tests

Permite comprobar que dry-run, staleness y fail-closed están cubiertos sin depender de un tenant real.

Documentación y ejemplos

Permite seguir el flujo de revisión y los ejemplos sin reconstruir el contexto desde el código.