Segmentación

Actualmente contamos con testigos y aprobadores para los sujetos Vino. Sin embargo, surge un problema con uno de los nodos que agregamos, SFO, ya que es específico de España y no queremos que influya en las decisiones tomadas en otros países.

Para abordar esta necesidad surge el concepto de segmentación por espacio de nombres. Esto nos permite definir permisos y roles específicos para ciertos espacios de nombres, asegurando que solo los nodos que consideramos válidos puedan acceder a información específica según nuestros intereses.

Con este nuevo conocimiento, es hora de seguir adaptando nuestro caso de uso. PremiumWines no sólo cuenta con viñedos en España sino también en Francia, lo que les permite elaborar botellas con distintos orígenes. Como sabemos, en España existe un organismo (SFO) capaz de aprobar el análisis de calidad del producto, pero este no es el caso en Francia, donde esta responsabilidad recae en WFO.

Para lograr lo que proponemos, necesitamos realizar algunos cambios en el esquema actual:

  • PremiumWines debería poder crear temas en ambos países, por lo que debe ser creador en los espacios de nombres “España” y “Francia”.
  • WFO se convierte en testigo y aprobador de vinos tanto en España como en Francia.
  • Se deberían permitir las invocaciones externas tanto en España como en Francia.
  • SFO sólo será aprobador y testigo de los vinos españoles.

Primero, verifiquemos las funciones de la gobernanza antes de realizar estos cambios:

Haremos cambios en los roles declarados en la gobernanza. Así es como deberían verse las propiedades después de las modificaciones:

Para generar estos cambios usaremos nuestra herramienta kore-Patch siguiendo este procedimiento:

kore-patch '{"roles":[{"namespace":"","role":"WITNESS","schema":{"ID":"governance"},"who":"MEMBERS"},{"namespace":"","role":"APPROVER","schema":{"ID":"governance"},"who":{"NAME":"WPO"}},{"namespace":"","role":"CREATOR","schema":{"ID":"Wine"},"who":{"NAME":"PremiumWines"}},{"namespace":"","role":"APPROVER","schema":{"ID":"governance"},"who":{"NAME":"WFO"}},{"namespace":"","role":"VALIDATOR","schema":{"ID":"governance"},"who":{"NAME":"WFO"}},{"namespace":"","role":"EVALUATOR","schema":{"ID":"governance"},"who":{"NAME":"WFO"}},{"namespace":"","role":"WITNESS","schema":{"ID":"Wine"},"who":{"NAME":"WFO"}},{"namespace":"","role":"ISSUER","schema":{"ID":"Wine"},"who":"NOT_MEMBERS"},{"namespace":"","role":"WITNESS","schema":{"ID":"Wine"},"who":{"NAME":"SFO"}},{"namespace":"","role":"APPROVER","schema":{"ID":"Wine"},"who":{"NAME":"SFO"}}]}' '{"roles":[{"namespace":"","role":"WITNESS","schema":{"ID":"governance"},"who":"MEMBERS"},{"namespace":"","role":"APPROVER","schema":{"ID":"governance"},"who":{"NAME":"WPO"}},{"namespace":"Spain","role":"CREATOR","schema":{"ID":"Wine"},"who":{"NAME":"PremiumWines"}},{"namespace":"France","role":"CREATOR","schema":{"ID":"Wine"},"who":{"NAME":"PremiumWines"}},{"namespace":"","role":"APPROVER","schema":{"ID":"governance"},"who":{"NAME":"WFO"}},{"namespace":"","role":"VALIDATOR","schema":{"ID":"governance"},"who":{"NAME":"WFO"}},{"namespace":"","role":"EVALUATOR","schema":{"ID":"governance"},"who":{"NAME":"WFO"}},{"namespace":"Spain","role":"WITNESS","schema":{"ID":"Wine"},"who":{"NAME":"WFO"}},{"namespace":"France","role":"WITNESS","schema":{"ID":"Wine"},"who":{"NAME":"WFO"}},{"namespace":"Spain","role":"APPROVER","schema":{"ID":"Wine"},"who":{"NAME":"WFO"}},{"namespace":"France","role":"APPROVER","schema":{"ID":"Wine"},"who":{"NAME":"WFO"}},{"namespace":"Spain","role":"ISSUER","schema":{"ID":"Wine"},"who":"NOT_MEMBERS"},{"namespace":"France","role":"ISSUER","schema":{"ID":"Wine"},"who":"NOT_MEMBERS"},{"namespace":"Spain","role":"WITNESS","schema":{"ID":"Wine"},"who":{"NAME":"SFO"}},{"namespace":"Spain","role":"APPROVER","schema":{"ID":"Wine"},"who":{"NAME":"SFO"}}]}'

El resultado obtenido será:

A continuación, invocaremos el método del contrato responsable de actualizar sus propiedades:

Después de enviar la solicitud de actualización de gobernanza, recibiremos una notificación de aprobación. Para hacer esto, ejecute el siguiente comando:

curl --request GET 'http://localhost:3000/approval-requests?status=Pending'

Copie el valor del campo id de la notificación y solicite la aprobación de WPO y WFO:

curl --request PATCH 'http://localhost:3000/approval-requests/{{PREVIUS-ID}}' \
--header 'Content-Type: application/json' \
--data-raw '{"state": "RespondedAccepted"}'
curl --request PATCH 'http://localhost:3002/approval-requests/{{PREVIUS-ID}}' \
--header 'Content-Type: application/json' \
--data-raw '{"state": "RespondedAccepted"}'

Si todo salió bien, cuando ejecute el siguiente comando, el sn debería ser 7 y deberían mostrarse los cambios realizados anteriormente:

curl --request GET 'http://localhost:3000/subjects?subject_type=governances'

Una vez implementada la segmentación del namespace, realizaremos pruebas para verificar su correcto funcionamiento.

Creemos una botella de vino francés usando el siguiente comando:

curl --request POST 'http://localhost:3001/event-requests' \
--header 'Content-Type: application/json' \
--data-raw '{
    "request": {
        "Create": {
        "governance_id": {{GOVERNANCE-ID}},
        "schema_id": "Wine",
        "namespace": "France",
        "name": "Wine"
        }
    }
}'

Cuando realices esta acción, recibirás un request-id, que deberás copiar y usar en el siguiente comando:

curl --request GET 'http://localhost:3001/event-requests/{{REQUEST-ID}}/state'

Este último comando te dará una respuesta similar a la siguiente:

{
    "id": "{{REQUEST-ID}}",
    "subject_id": "{{SUBJECT-ID}}",
    "sn": 0,
    "state": "finished",
    "success": true
}

Para comprobar nuestra nueva botella de vino, ejecute el siguiente comando:

curl --request GET 'http://localhost:3001/subjects/{{SUBJECT-ID}}'
{
    "subject_id": "{{SUBJECT-ID}}",
    "governance_id": "{{GOVERNANCE-ID}}",
    "sn": 0,
    "public_key": "E5DkRaljajwUZ1HrpgdkIxdTu0fbrg-nqoBJFHqm6GJY",
    "namespace": "France",
    "name": "Wine",
    "schema_id": "Wine",
    "owner": "{{CONTROLLER-ID}}",
    "creator": "{{CONTROLLER-ID}}",
    "properties": {
        "grape": null,
        "harvest": 0,
        "organic_certified": null,
        "origin": "",
        "temperature_control": {
            "last_check": 0,
            "temperature_ok": true
        }
    },
    "active": true
}

Pero si ejecutamos:

curl --request GET 'http://localhost:3000/subjects/{{SUBJECT-ID}}'

Obtenemos un error 404 debido a la segmentación que hemos aplicado cambiando el espacio de nombres, que determina quiénes son los testigos del sujeto.

Inicialice la botella antes de probar la emisión del evento de certificación:

curl --request POST 'http://localhost:3001/event-requests' \
--header 'Content-Type: application/json' \
--data-raw '{
    "request": {
        "Fact": {
            "subject_id": {{SUBJECT-ID}},
            "payload": {
                "Init": {
                    "harvest": 2,
                    "grape": "Chardonnay",
                    "origin": "france"
                }
            }
        }
    }
}'

Ahora, cuando ejecute la consulta de sujeto nuevamente, debería tener un valor sn de 1 y mostrar la información mencionada anteriormente:

curl --request GET 'http://localhost:3001/subjects/{{SUBJECT-ID}}'
{
    "subject_id": "{{SUBJECT-ID}}",
    "governance_id": "{{GOVERNANCE-ID}}",
    "sn": 1,
    "public_key": "E5DkRaljajwUZ1HrpgdkIxdTu0fbrg-nqoBJFHqm6GJY",
    "namespace": "France",
    "name": "Wine",
    "schema_id": "Wine",
    "owner": "{{CONTROLLER-ID}}",
    "creator": "{{CONTROLLER-ID}}",
    "properties": {
        "grape": "Chardonnay",
        "harvest": 2,
        "organic_certified": null,
        "origin": "france",
        "temperature_control": {
            "last_check": 0,
            "temperature_ok": true
        }
    },
    "active": true
}

Probaremos la emisión del evento de certificación. Para ello generaremos la firma del evento que queremos emitir usando kore-Sign, con el siguiente formato, reemplazando subject_id por el identificador de nuestro sujeto vino:

kore-sign 'f855c6736463a65f515afe7b85d1418c096ed73852b42bbe4c332eb43d532326' '{"Fact":{"subject_id":"{{SUBJECT-ID}}","payload":{"OrganicCertification":{"fertilizers_control":false,"pesticides_control":false,"analytics":false,"additional_info":"test"}}}}'

El resultado de esta ejecución se incluirá en la siguiente solicitud:

curl --request POST 'http://localhost:3001/event-requests' \
--header 'Content-Type: application/json' \
--data-raw {{SIGN-RESULT}}

Esto nos dará un resultado similar al siguiente:

curl --request POST 'http://localhost:3001/event-requests' \
--header 'Content-Type: application/json' \
--data-raw '{
    "request": {
        "Fact": {
        "subject_id": {{SUBJECT-ID}},
        "payload": {
            "OrganicCertification": {
            "additional_info": "test",
            "analytics": false,
            "fertilizers_control": false,
            "pesticides_control": false
            }
        }
        }
    },
    "signature": {
        "signer": "EzzmRjc8CtjzHu3MKmuTgnmOTgrJlYZj1D2DCZ9nN7Vk",
        "timestamp": 1689858060412988735,
        "value": "SEiF6C6zhFxzxs56nY6vk4ySTl7zvpV2gExTiiGlbxKI-HVvizL6eYmjV9IjE8GJMzOIQkok8rUehRVK9cNgSfCg"
    }
}'

Si la segmentación se ha aplicado correctamente, el mensaje de aprobación para este sujeto solo debería haberlo recibido WFO. Para comprobarlo, ejecute el siguiente comando:

curl --request GET 'http://localhost:3002/approval-requests?status=pending'

Copie su id y utilícelo para aceptarlo con la siguiente solicitud:

curl --request PATCH 'http://localhost:3002/approval-requests/{{PREVIUS-ID}}' \
--header 'Content-Type: application/json' \
--data-raw '{"state": "RespondedAccepted"}'

Ahora, cuando vuelvas a consultar el asunto, debería mostrar un valor sn de 2, y el campo organic_certified debería ser false:

curl --request GET 'http://localhost:3001/subjects?subject_type=all&governanceid={{GOVERNANCE-ID}}'
{
    "subject_id": "{{SUBJECT_ID}}",
    "governance_id": "{{GOVERNANCE-ID}}",
    "sn": 2,
    "public_key": "E5DkRaljajwUZ1HrpgdkIxdTu0fbrg-nqoBJFHqm6GJY",
    "namespace": "France",
    "name": "Wine",
    "schema_id": "Wine",
    "owner": "{{CONTROLLER-ID}}",
    "creator": "{{CONTROLLER-ID}}",
    "properties": {
        "grape": "Chardonnay",
        "harvest": 2,
        "organic_certified": false,
        "origin": "france",
        "temperature_control": {
            "last_check": 0,
            "temperature_ok": true
        }
    },
    "active": true
}