Published

Fase 1 — PoC local del conector EDC (el cimiento)

Connect any source, model it as an ontology, transform it, and operationalize it, analytics, automation and machine learning, under one governed, self-hostable roof. --- Most teams stitch the...

Fase 1 — PoC local del conector EDC (el cimiento)

Documento padre: edc-connector-research.md
Estado: approach / plan de ejecución.
Naturaleza: esta fase es el cimiento. No es "correr un tutorial": es dejar establecido el conocimiento, el arnés reproducible y la superficie de API sobre los que se construye todo lo demás.


1. Filosofía — qué es y qué no

Qué es: levantar dos conectores EDC en local (provider + consumer), con stores en memoria, y recorrer a mano el ciclo completo del Dataspace Protocol — publicar un asset → verlo en el catálogo → negociar contrato → transferir el dato — usando la Management API real. El objetivo no es "que funcione", es entenderlo hasta poder reimplementar las llamadas desde Node con los ojos cerrados.

Qué NO es (fuera de alcance, a propósito):

  • ❌ Ninguna integración con Carbon todavía (nada de executor, cliente Node, UI, workers).
  • ❌ Nada de IdentityHub / DID / VC — IAM en memoria (eso es Fase 6).
  • ❌ Nada de R2 real ni Iceberg (eso es Fase 2; aquí solo sondeamos, §6).
  • ❌ Nada de escribir extensiones Java propias — usamos los launchers de los samples tal cual (EDC = caja negra tras su REST API).

Por qué esta disciplina: el foso del producto es la simplicidad operable por un equipo de 3. Si en el cimiento ya nos enredamos con Kubernetes, identidad descentralizada y Java custom, perdemos. Primero fluidez con la interfaz (Management API), lo demás se apila después.


2. Objetivos medibles (lo que el cimiento debe dejar)

  1. Ciclo DSP end-to-end funcionando en local: catálogo → negociación → transferencia, en modo push y pull.
  2. Superficie de API capturada: la colección exacta de requests Management API (endpoints + payloads JSON-LD) que Carbon replicará. → semilla directa de lib/dataspaces/edc-client.ts (Fase 3).
  3. Arnés reproducible: los dos conectores se levantan con un comando, versión pineada, en cualquier máquina (base del futuro services/edc-service/).
  4. Riesgos downstream despejados (respuestas escritas, §6): ¿el data plane apunta a S3/R2? ¿la asincronía se maneja por polling o por eventos? ¿qué forma tienen los payloads?
  5. Decisiones de arranque documentadas (§3): versión EDC, versión de Management API, distribución elegida.

3. Decisiones de arranque (las que fijan el cimiento)

DecisiónElecciónPor qué
Distribución de partidaeclipse-edc/Samples (scopes basic + transfer)Es el camino oficial para aprender la Management API. NO el Minimum Viable Dataspace (trae Kubernetes + IdentityHub → demasiado pesado y mete identidad antes de tiempo).
VersiónPinear un tag/release estable de Samples (que fija su versión de EDC)EDC es 0.x y se mueve rápido. Reproducibilidad = requisito del producto. Anotar el commit exacto.
Management APILa que traiga el tag (hoy v3, migrando a v4)Registrar la versión: los endpoints/payloads cambian entre v3 y v4.
PersistenciaIn-memory stores + vaultCero infra en el PoC (como el MVD desde IntelliJ). Postgres/Vault entran en producción (Fase 8).
Runnerdocker-compose con 2 servicios (provider, consumer)Reproducible y cross-platform (clave en Windows, §4). Alternativa dev rápida: Gradle/IntelliJ.
Herramienta de interacciónFicheros .http / colección (curl como fallback)Cada request queda versionado = la superficie de API.

4. Prerrequisitos de entorno (nota Windows)

  • JDK 17+ y Gradle (los samples usan el wrapper ./gradlew).
  • Docker Desktop — para el arnés reproducible.
  • Git.

⚠️ Estamos en Windows. Java/Gradle son cross-platform, pero los tutoriales de EDC asumen bash/curl. Para evitar fricción: ejecutar el ciclo dentro de docker-compose (recomendado) o usar WSL2 / Git Bash para los comandos del sample. No pelear con PowerShell + curl.exe en el PoC.


5. Ruta paso a paso (mapeada a los samples reales)

Cada paso añade una pieza del modelo mental. Ir en orden.

Paso 0 — Entorno + pin

Clonar eclipse-edc/Samples, checkout del tag elegido, verificar ./gradlew compila. Anotar versión.

Paso 1 — Scope basic (leer, no profundizar)

Hojear los samples basic solo para entender el patrón EDC: extensión + inyección de dependencias + launcher (build.gradle.kts decide las capacidades). No hay que escribir Java; hay que reconocer la anatomía para más adelante saber dónde entra el DataSource Iceberg custom (Estrategia B, §3.1 del doc padre).

Paso 2 — transfer-00-prerequisites (⭐ el paso que más enseña)

Compilar el connector library, arrancar provider y consumer, y crear vía Management API:

  • un Asset (apunta a un dataAddress, aquí un endpoint HTTP demo),
  • una Policy (ODRL),
  • una Contract Definition (empareja asset ↔ policy).

Aquí se aterriza el modelo de datos de §3 del doc padre. Endpoints típicos a capturar:

POST /management/v3/assets
POST /management/v3/policydefinitions
POST /management/v3/contractdefinitions

Paso 3 — Catálogo (primer mensaje DSP entre conectores)

El consumer pide el catálogo del provider:

POST /management/v3/catalog/request   → devuelve el catálogo DCAT con la oferta

Hito: dos conectores hablando DSP. Guardar el JSON-LD del catálogo (de ahí sale el policy/offer id para negociar).

Paso 4 — transfer-01-negotiation (la asincronía)

Iniciar negociación y pollear hasta FINALIZED:

POST /management/v3/contractnegotiations      → devuelve { "@id": negotiationId }
GET  /management/v3/contractnegotiations/{id} → state: REQUESTED→…→FINALIZED (+ contractAgreementId)

Aprendizaje clave: la Management API es una máquina de estados asíncrona. Esto define cómo será el worker de Carbon (Fase 4): polling vs eventos (ver Paso 7).

Paso 5 — transfer-02-provider-push (primer dato movido)

Con el contractAgreementId, iniciar transferencia; el provider empuja el dato a un endpoint HTTP del consumer:

POST /management/v3/transferprocesses      → { "@id": transferId }
GET  /management/v3/transferprocesses/{id} → state → COMPLETED

Es la Estrategia A (copia) de §3.1 en su forma más simple.

Paso 6 — transfer-03-consumer-pull (el modelo que más usaremos)

HTTP Proxy Data Plane: el consumer recibe un EDR (Endpoint Data Reference) y tira del dato cuando quiere:

POST /management/v3/edrs/... (o el endpoint de EDR del tag)  → token + endpoint
GET  <data-plane-public-url>  (con el token)                 → los bytes

El pull es el que mejor encaja con "el dato bajo demanda" y es el escalón hacia el zero-copy (Estrategia B).

Paso 7 — transfer-04-event-consumer (opcional pero recomendado)

Reaccionar a eventos del conector en vez de pollear. Decide el diseño del edc-sync-worker de Carbon: si los eventos son fiables, el worker escucha en lugar de sondear → más eficiente.


6. Sondas de futuro (de-risking — investigación, no construcción)

Sin salirnos del alcance, dejar respondido por escrito (mirando docs/código, o un mini-experimento acotado):

  • Data plane S3 → R2 (de-risk Fase 2): confirmar cómo el data plane S3 de EDC (Technology-Aws) se configura con endpointOverride. Stretch opcional: levantar MinIO local como stand-in de R2 y hacer un transfer con destino S3. Si sale, la Fase 2 queda casi resuelta.
  • Punto de extensión Iceberg (de-risk Fase 5/Estrategia B): identificar dónde en la anatomía del connector entraría un DataSource custom que exponga una tabla vía el catálogo REST de Lakekeeper. Solo localizar el gancho, no implementarlo.
  • Forma de las políticas ODRL: capturar 2-3 ejemplos de policy (acceso libre, restricción geográfica, caducidad) → base del futuro editor de gobernanza.

7. Entregables (lo que queda como cimiento)

  1. services/edc-service/poc/ — docker-compose + configs + tag pineado + script de arranque de 1 comando. (Semilla del servicio real; el launcher propio con módulos S3 llega en Fase 2.)
  2. docs/dataspaces/fase-1-findings.md — al terminar: versión EDC/API usada, decisiones confirmadas, respuestas a las sondas (§6), y sorpresas.
  3. Colección de requests (.http/Postman versionada) — la superficie de API anotada = semilla de edc-client.ts.
  4. Diagrama de secuencia real con los endpoints concretos del ciclo (para pitch y para la Fase 3).

8. Definition of Done

  • El consumer obtiene un asset del provider end-to-end, en push y en pull, en local.
  • Todo se levanta con un comando y versión pineada (reproducible en otra máquina).
  • Está capturado cada request Management API del ciclo (assets, policies, contract defs, catalog, negotiation, transfer, edr).
  • Sabemos exactamente qué endpoints y payloads implementará lib/dataspaces/edc-client.ts.
  • fase-1-findings.md responde: ¿data plane S3/R2? ¿polling vs eventos? ¿forma de payloads JSON-LD? ¿versión de Management API?

9. Riesgos de la propia Fase 1

RiesgoMitigación
Java/Gradle poco familiarEDC como caja negra; usar launchers de los samples sin tocarlos.
Versiones que no cuadran (0.x)Pinear tag; anotar versión de EDC y de Management API (v3 vs v4).
Fricción en Windowsdocker-compose (o WSL2/Git Bash) para los comandos del sample.
Scope creep (identidad, R2, Iceberg)Están fuera a propósito (§1). Las sondas (§6) son lectura, no construcción.
PoC que se vuelve deudaSeparar limpio: samples = aprendizaje desechable; poc/ = arnés reproducible que sí evoluciona.

10. Qué desbloquea para las siguientes fases

  • Fase 2 (data plane sobre R2) ← sonda S3/MinIO + arnés reproducible.
  • Fase 3 (cliente Node + executor) ← superficie de API capturada.
  • Fase 4 (consumir → lakehouse) ← decisión polling vs eventos.
  • Fase 5 (publicar datasets) ← modelo Asset/Policy/ContractDefinition ya interiorizado + gancho Iceberg localizado.

Siguiente acción concreta: scaffolding de services/edc-service/poc/ (docker-compose de 2 conectores + tag pineado). ¿Lo genero?