Published

Fase 1 — Hallazgos (PoC EDC ejecutado)

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 — Hallazgos (PoC EDC ejecutado)

Resultado: ✅ ciclo DSP completo end-to-end, con dato real transferido.
Ejecutado el 2026-07-02. Approach: fase-1-poc-approach.md · Arnés: services/edc-service/poc/


1. Qué se logró

Dos conectores EDC en Docker recorrieron el ciclo completo del Dataspace Protocol:

Provider: crea Asset → Policy → Contract Definition
Consumer: catálogo → negociación (INITIAL→REQUESTED→FINALIZED) → acuerdo
          → transfer HttpData-PULL (INITIAL→REQUESTED→STARTED) → EDR
Cliente:  PULL con token EDR → 5645 bytes reales de jsonplaceholder/users ✓

Un comando levanta todo (docker compose up -d --build), otro recorre el ciclo (bash run-cycle.sh). Cada respuesta quedó capturada en services/edc-service/poc/out/.


2. Versiones (el pin)

CosaValorNota
eclipse-edc/Samples SHAcc7a7e35dd37eae5f3646d0d87c1593e9f573f0eARG SAMPLES_SHA en el Dockerfile.
Dataspace Protocol2025-1path /protocol/2025-1, contexto https://w3id.org/dspace/2025/1/.
Management APIv3⚠️ DEPRECADA — el conector avisa "switch to V4, V3 will be removed". Ver §6.
IAMmock (iam.mock)Sin identidad real; DID/VC es Fase 6.
Runtime buildJDK 17 (en Docker)Host tiene Java 1.8 → todo se construye en Docker.

3. Superficie de API capturada (semilla de lib/dataspaces/edc-client.ts)

Todas contra la Management API v3. Base: provider :19193, consumer :29193.

#MétodoPathLadoDevuelve
1POST/management/v3/assetsproviderel asset creado
2POST/management/v3/policydefinitionsproviderla policy
3POST/management/v3/contractdefinitionsproviderla contract def
4POST/management/v3/catalog/requestconsumercatálogo DCAT (contiene el offer id)
5POST/management/v3/contractnegotiationsconsumerIdResponse con @id (negotiationId)
6GET/management/v3/contractnegotiations/{id}consumerestado + contractAgreementId
7POST/management/v3/transferprocessesconsumerIdResponse con @id (transferId)
8GET/management/v3/transferprocesses/{id}consumerestado
9GET/management/v3/edrs/{transferId}/dataaddressconsumerDataAddress (endpoint + token bearer)
10GET<edr.endpoint> + header Authorization: <edr.authorization>data planeel dato

Formas clave de respuesta:

  • IdResponse: {"@type":"IdResponse","@id":"<uuid>","createdAt":<ms>,"@context":[...]}
  • offer id (catálogo): en dcat:dataset.odrl:hasPolicy.@id, formato base64:base64:uuid (p. ej. MQ==:YXNzZXRJZA==:<uuid>). Debe copiarse tal cual en la oferta de negociación (policy.@id).
  • EDR: {"@type":"edc:DataAddress","type":"https://w3id.org/idsa/v4.1/HTTP","endpoint":"...","authType":"bearer","authorization":"<JWT>"}

4. Aprendizaje central: es una máquina de estados asíncrona

Negociación y transferencia no son síncronas: el POST devuelve un ID y el estado avanza en background.

  • Negociación observada: INITIAL → REQUESTED → FINALIZED.
  • Transfer observado: INITIAL → REQUESTED → STARTED (en consumer pull se queda en STARTED).

Decisión de diseño para Carbon (Fase 4): el edc-sync-worker debe pollear estos estados (o suscribirse a eventos, sample transfer-04, no probado aún). El modelo poll está validado y es simple; evaluar eventos si el volumen lo pide.


5. Respuestas a las sondas de riesgo (§6 del approach)

SondaResultado
Async: poll vs eventos✅ Resuelto: poll funciona y es directo (§4). Eventos = pendiente (transfer-04).
Forma de payloads JSON-LD✅ Capturada (§3). Contextos @vocab EDC + ODRL + DSP 2025/1.
Data plane S3 → R2 (Fase 2)🟡 Pendiente: este PoC usó HttpData (jsonplaceholder), no S3. La sonda MinIO/R2 no se ejecutó. Es el primer objetivo de Fase 2.
Gancho para DataSource Iceberg (Fase 5/Estrategia B)Localizado: el provider de transfer-03 es un ejemplo de data plane custom — CustomProxyDataPlaneExtension registra un PortMapping + un generatorFunction de EDRs + un ProxyController. Ese es exactamente el patrón de extensión donde enchufaría un DataSource que sirva una tabla Iceberg vía Lakekeeper.

6. Sorpresas / notas para producción

  1. Management API v3 está deprecada → planificar v4 antes de escribir edc-client.ts (Fase 3). Los payloads y paths pueden cambiar. Acción: al empezar Fase 3, repetir el ciclo contra v4 y recapturar la superficie.
  2. Networking entre contenedores: hubo que sobreescribir edc.dsp.callback.address a nombres de servicio docker (http://provider:19194/...) en vez de localhost; si no, los conectores no se alcanzan. Aprendizaje directo para el despliegue real (Fase 8).
  3. Readiness: POST /management/v3/assets/request con body vacío devuelve 400 (no 200) pero significa "servidor arriba". El probe lo trata como listo.
  4. Entorno Windows: host con Java 1.8 y sin jq; build en Docker y parseo con grep/sed. sleep en primer plano lo bloquea el harness → el script usa perl como fallback para las esperas.
  5. Pull desde el host: el edc.dataplane.proxy.public.endpoint se dejó como localhost:19291 a propósito, para que el cliente (host) haga el pull con el puerto publicado. El token EDR valida sin importar el host usado.

7. Definition of Done (del approach)

  • Consumer obtiene un asset del provider end-to-end (pull). (push = transfer-02, no ejecutado; el pull cubre el objetivo).
  • Todo se levanta con un comando y versión pineada, reproducible.
  • Capturado cada request Management API del ciclo (out/).
  • Sabemos qué endpoints/payloads implementará edc-client.ts (§3).
  • Respondidas las sondas (§5) — salvo S3/R2, que arranca Fase 2.

8. Cómo reproducir

cd services/edc-service/poc
docker compose up -d --build   # build (~minutos la 1ª vez) + arranque
bash run-cycle.sh              # ciclo DSP completo → out/
docker compose down            # parar

9. Puente a la Fase 2

  1. v4: recapturar la superficie de API contra Management API v4.
  2. Data plane S3 → R2: añadir el módulo S3 al launcher + MinIO local como stand-in de R2; transferir un objeto a un prefijo del bucket. Es la sonda que quedó abierta.
  3. Empezar a modelar services/edc-service/ "de verdad" (launcher propio con los módulos que necesitamos), tomando este poc/ como referencia.