odrl icon indicating copy to clipboard operation
odrl copied to clipboard

example - a call for evaluation / response

Open joshcornejo opened this issue 7 months ago • 4 comments

Developers of clients ("those that call an evaluator") can benefit from having an example of one simple interface compliant with authZen ("the call") or RFC-9396 ("the response"):

Client call:

context:

  "context" : {
    "did" : "did:odrl:0196a09b-364a-71a6-926b-ec6a26b312ba"
  },

It is the wrapper for the state of the world (SoW) when passed as a parameter from the client, in the case of a server-based implementation, the expected key is did.

actor or subject:

  "subject" : { 
    "uid" : "a97b768a-db9b-4523-9e2c-06031933ca59",
    "location" : "ES-MD"
  },

Since the subject state/status is known to the callee, key entries such as location are expected to be part of the subject. In the example above, we use ISO 3166 - 2 to describe that the subject is located in Comunidad de Madrid, Spain.

note:

  • The key "subject" is synonymous with "actor",
  • "uid" and "id" can be used interchangeably

action:

  "action" : {
    "taxonomy" : "odrl",
    "value" : "read"
  },

There are no expected keys passed on the call other than the value. Taxonomy prefixing is optional (it is unlikely that a combination of agreements and state of the world includes 2 ontologies with the same value for an action with different semantics, e.g. abc:XXX and def:XXX).

asset or resource:

  "resource" : { 
    "uid" : "6b65977c-9dd8-4989-80f4-225b96258645"
  }

There are no further keys expected.

note:

  • The key "resource" is synonymous with "asset",
  • "uid" and "id" can be used interchangeably

Full JSON:

example 1:

{
  "context" : {
    "did" : "did:odrl:0196a09b-364a-71a6-926b-ec6a26b312ba"
  },
  "subject" : {
    "id" : "a97b768a-db9b-4523-9e2c-06031933ca59",
    "location" : "ES-MD"
  },
  "action" : {
    "value" : "read"
  },
  "resource" : { 
    "id" : "6b65977c-9dd8-4989-80f4-225b96258645"
  }
}

example 2:

{
  "context" : {
  },
  "actor" : {
    "uid" : "a97b768a-db9b-4523-9e2c-06031933ca59"
  },
  "action" : {
    "taxonomy": "odrl",
    "value" : "read"
  },
  "asset" : { 
    "uid" : "6b65977c-9dd8-4989-80f4-225b96258645"
  }
}

Evaluator Response:

The response is a JSON-LD compatible output that starts with the @context keyword

  "@context": [
    "string"
  ],

literals:

  "versionMajor": 1,
  "versionMinor": 1,
  "id": "string",
  "status": 1,
  "expiry": 1,
  "decision": false,
  "encryptedData": "string",
  • 2 entries for version control (major & minor)
  • an RFC 9592 id for the response.
  • status: 0 means that there are no obligations to be fulfilled, any other value is the epoch timestamp for this request to expire and track of obligations lost (there can be extensions for this but depends on agreement on obligations)
  • expiry: a non-zero value provides the client with the caching time for this request
  • decision: the boolean value of the outcome of the call
  • encryptedData: if the interactions are encrypted, the output will be in this field (and the "data" field will be empty).

compound elements: telemetry

  "call": {
    "worldId": "string",
    "subject": {},
    "action": {},
    "resource": {}
  },
  "timestamp": {
  },

The call parameters and any performance details (for debugging) obligations

  "obligations": [
    {
      "id": "string",
      "expiry": 1,
      "dutyId": "string",
      "trigger": {
        "agreementId": "string",
        "ruleId": "string",
        "actor": "string",
        "action": "string",
        "asset": "string",
        "relationship": "string"
      },
      "responsibilities": [
        {
          "action": [
            "string"
          ],
          "operand": "string",
          "conditions": [
            {
              "leftOperand": "string",
              "operator": "string",
              "rightOperand": "string"
            }
          ]
        }
      ],
      "fullfilled": false
    }
  ],

A list of all the obligations that must be fullfilled, of relevance:

  • id: representing a ULID for the 'obligation'
  • expiry: the allocated time by the creator of the rule for the obligation to be fulfilled (e.g. "the client has 10 minutes to fulfill the obligation")
  • dutyId: the uid of the obligation Rule
  • trigger: an object that points at the detail entry that triggered the obligation
  • responsibilities: the action and the conditions that the client needs to fulfil.
  • fulfilled: if this specific obligation has been fulfilled or not.

data

  "data": {
    "activated": true,
    "decision": true,
    "audit": {
      "admin": [
        {
          "msg": "string",
          "decision": true,
          "id": "string",
          "span": "string",
          "trail": []
        }
      ],
      "client": []
    }
  }

data provides detailed information about the deontic state (activated and decision) with audit trails for the client ("caller" - for example if a variable in the state of the world hasn't been set, a message informing the client will be passed back) and the admin (for example the hierarchy of evaluations that took place: agreement -> rule -> refinement -> logical constraint -> constraint)

NOTE: Client-based state of the world and RFC-9396 calls could lead to "JWT bloating", so designs should take care of its impact.

joshcornejo avatar May 20 '25 14:05 joshcornejo

This is very relevant to https://github.com/w3c/odrl/issues/118

I see something else, actually: I can conceive situations in which the state of the world is huge. My opinion: the state of the world should be also communicable via reference. A "pointer" instead of the whole data should do the job as well. @besteves4 @AndreaCimminoArriaga @YassirSellami what do you think?

vroddon avatar Jun 04 '25 10:06 vroddon

In my proposal to JPG Trust, the image can contain a DID with an SoW & Agreement embedded (simple cases where it is not necessary to track a lot) or a reference to the DID that can be found by DID resolution (when DID registers exist).

joshcornejo avatar Jun 04 '25 10:06 joshcornejo

I think the output especially the one with debugging data can useful, as the detail for each rule and constraints can be useful for "Usage Control or Monitoring Scenarios" or for a policy based on the output of a first policy.

For the input, I think we should start discussing the exact ontology and Json context in reference, I tried to come up with a proposal that is quite similar in the other issue: https://github.com/w3c/odrl/issues/118#issuecomment-2943262788

YassirSellami avatar Jun 05 '25 08:06 YassirSellami

The sate of the world (SoW) as input for the evaluator can be a filtered version of the whole state of the world, from a conceptual point of view the state of the world is all the information needed to evaluate a policy. From an implementation point of view, it does not necessarily means we need to pass the whole database. There are ways of filtering the SoW, one is the suggested by victor with a pointer (quite elegant in my opinion). If we assume the SoW is a knowledge graph, also named graph could be used, or a SPARQL query with relevant values taken from the policy in order to filter the SoW graph.

The important thing in any case, IMHO is to separate the formal semantics (formalization) from the implementation since the SoW is handled differently.

AndreaCimminoArriaga avatar Jun 05 '25 09:06 AndreaCimminoArriaga