A [=Contract Negotiation=] involves two parties, a [=Provider=] that offers one or more [=Datasets=] along with a [=Policy=] and a [=Consumer=] that requests [=Datasets=]. A [=Contract Negotiation=] is uniquely identified through an Internationalized Resource Identifier (IRI) [[rfc3987]]. Each [=Contract Negotiation=] requires a newly generated IRI, which MAY not be used in a [=Contract Negotiation=] after a terminal state has been reached. A [=Contract Negotiation=] progresses through a series of states, which are tracked by the [=Provider=] and [=Consumer=] using [=Messages=]. A [=Contract Negotiation=] transitions to a state in response to an acknowledged [=Message=] from the counter-party. Both parties have the same state of the [=Contract Negotiation=]. In case the states differ, the [=Contract Negotiation=] MUST be terminated and a new [=Contract Negotiation=] MAY be initiated.
The [=Contract Negotiation=] states are:
- REQUESTED: An [=Agreement=] for a [=Dataset=] has been requested by the [=Consumer=] based on an [=Offer=] and the [=Provider=] has sent an ACK response.
- OFFERED: The [=Provider=] has sent an [=Offer=] to the [=Consumer=] and the [=Consumer=] has sent an ACK response.
- ACCEPTED: The [=Consumer=] has accepted the latest [=Offer=] and the [=Provider=] has sent an ACK response.
- AGREED: The [=Provider=] has accepted the latest [=Offer=], sent an [=Agreement=] to the [=Consumer=], and the [=Consumer=] has sent an ACK response.
- VERIFIED: The [=Consumer=] has sent an [=Agreement=] verification to the [=Provider=] and the [=Provider=] has sent an ACK response.
- FINALIZED: The [=Provider=] has sent a finalization [=Message=] including his own [=Agreement=] verification to the [=Consumer=] and the [=Consumer=] has sent an ACK response. Data is now available to the [=Consumer=].
- TERMINATED: The [=Provider=] or [=Consumer=] has placed the [=Contract Negotiation=] in a terminated state. A termination [=Message=] has been sent by either of the [=Participants=] and the other has sent an ACK response. This is a terminal state.
The [=Contract Negotiation=] state machine is represented in the following diagram:
Transitions marked with C indicate a [=Message=] sent by the [=Consumer=], transitions marked with P indicate
a [=Provider=] [=Message=]. Terminal states are final; the state machine MUST NOT transition to another state. A new [=Contract Negotiation=] MAY be initiated if, for instance, the [=Contract Negotiation=] entered the TERMINATED state due to a network issue.
The [=Contract Negotiation=] state machine is transitioned upon receipt and acknowledgement of a [=Message=]. This section details those [=Messages=] as abstract [=Message Types=].
-
Concrete wire formats are defined by the protocol binding, e.g., Contract Negotiation HTTPS Binding.
-
All [=Policy=] types ([=Offer=], [=Agreement=]) MUST contain a unique identifier in the form of a URI. Globally Unique Identifiers (GUIDs) MAY also be used in the form of Uniform Resource Names (URNs), for instance following the pattern urn:uuid:{GUID}.
-
An [=Agreement=] MUST have a
targetproperty containing the [=Dataset=] identifier.
| Sent by | [=Consumer=] |
| Resulting state | REQUESTED, TERMINATED |
| Response | ACK or ERROR |
| Schema | JSON Schema |
| Example | Initiating Message, Message |
| Properties |
The Contract Request Message is sent by a [=Consumer=] to initiate a [=Contract Negotiation=] or to respond to a Contract Offer Message sent by a [=Provider=].
-
The [=Consumer=] MUST include an
offerproperty, which itself MUST have a@idproperty. If the message includes aproviderPidproperty, the request MUST be associated with an existing [=Contract Negotiation=] and a [=Consumer=] [=Offer=] MUST be created using either theofferoroffer.@idproperties. If the message does not include aproviderPid, a new [=Contract Negotiation=] MUST be created on [=Provider=] side using either theofferoroffer.@idproperties and the [=Provider=] MUST select an appropriateproviderPid. -
An
offer.@idMUST generally refer to an [=Offer=] contained in a [=Catalog=]. If the [=Provider=] is not aware of theoffer.@idvalue, it MUST respond with an error message. -
offer.obligationandoffer.permissionsignify the terms at which a [=Consumer=] would accept an [=Offer=]. -
The
callbackAddressis a URL indicating where messages to the [=Consumer=] SHOULD be sent in asynchronous settings. If the address is not understood, the [=Provider=] MUST return an unrecoverable error. -
Different to a [=Catalog=] or [=Dataset=], the [=Offer=] inside a Contract Request Message MUST have a
targetattribute. However, it's contained Rules MUST not have anytargetattributes to prevent inconsistencies with the ODRL inferencing rules for compact policies.
| Sent by | [=Provider=] |
| Resulting state | OFFERED, TERMINATED |
| Response | ACK or ERROR |
| Schema | JSON Schema |
| Example | Example Initial Message, Example Message |
| Properties |
The Contract Offer Message is sent by a [=Provider=] to initiate a [=Contract Negotiation=] or to respond to a Contract Request Message sent by a [=Consumer=].
-
If the message includes a
consumerPidproperty, the request MUST be associated with an existing [=Contract Negotiation=]. If the message does not include aconsumerPid, a new [=Contract Negotiation=] MUST be created on [=Consumer=] side and the [=Consumer=] selects an appropriateconsumerPid. -
The [=Dataset=] identifier MAY be included when the [=Provider=] initiates a [=Contract Negotiation=].
-
Different to a [=Dataset=], the [=Offer=] inside a Contract Offer Message MUST have a
targetattribute. However, its contained Rules MUST NOT have anytargetattributes to prevent inconsistencies with the ODRL inferencing rules for compact policies. -
If the message initiates a [=Contract Negotiation=], it MUST contain a
callbackAddressproperty indicating where messages to the [=Provider=] SHOULD be sent in asynchronous settings. If the address is not understood, the [=Consumer=] MUST return an unrecoverable error.
| Sent by | [=Provider=] |
| Resulting state | AGREED, TERMINATED |
| Response | ACK or ERROR |
| Schema | JSON Schema |
| Example | Message |
| Properties |
The Contract Agreement Message is sent by a [=Provider=] when it agrees to a [=Policy=]. It contains the complete [=Agreement=].
-
The message MUST contain a
consumerPidand aproviderPid. -
The message MUST contain an [=Agreement=].
-
An [=Agreement=] MUST contain a
timestampproperty defined as an XSD DateTime type. -
An [=Agreement=] MUST contain an
assignerandassignee. The contents of these properties are a dataspace-specific unique identifier of the [=Agreement=] parties. These identifiers MAY be the same as the identifiers of the [=Participant Agents=] negotiating the [=Agreement=] (e.g., [=Connectors=]). -
An [=Agreement=] MUST contain a
targetproperty. None of its Rules, however, MUST have anytargetattributes to prevent inconsistencies with the ODRL inferencing rules for compact policies.
| Sent by | [=Consumer=] |
| Resulting state | VERIFIED, TERMINATED |
| Response | ACK or ERROR |
| Schema | JSON Schema |
| Example | Message |
| Properties |
The Contract Agreement Verification Message is sent by a [=Consumer=] to verify the acceptance of an [=Agreement=].
-
A [=Provider=] MUST respond with an error if the [=Agreement=] cannot be validated or is incorrect.
-
The message MUST contain a
consumerPidand aproviderPid.
| Sent by | [=Consumer=], [=Provider=] |
| Resulting state | FINALIZED, ACCEPTED, TERMINATED |
| Response | ACK or ERROR |
| Schema | JSON Schema |
| Example | Message |
| Properties |
When the Contract Negotiation Event Message is sent by a [=Provider=] with an eventType property set to FINALIZED,
an [=Agreement=] has been finalized and the associated [=Dataset=] is accessible. The state machine is transitioned to
the FINALIZED state.
-
Other event types MAY be defined in the future.
-
A [=Consumer=] MUST respond with an error if the [=Agreement=] cannot be validated or is incorrect.
-
The message MUST contain a
consumerPidand aproviderPid. -
When the message is sent by a [=Consumer=] with an
eventTypeset toACCEPTED, the state machine MUST be placed in theACCEPTEDstate. -
It is an error for a [=Consumer=] to send the message with an event type
FINALIZEDto the [=Provider=]. -
It is an error for a [=Provider=] to send the message with an event type
ACCEPTEDto the [=Consumer=].
Note that [=Contract Negotiation=] events are not intended for propagation of an [=Agreement=] state after a [=Contract Negotiation=] has entered a terminal state. [=Consumer=] or [=Provider=] MUST NOT send an event after the [=Contract Negotiation=] state machine has entered a terminal state. If they do so, this event MUST be handled as error.
| Sent by | [=Consumer=], [=Provider=] |
| Resulting state | TERMINATED |
| Response | ACK or ERROR |
| Schema | JSON Schema |
| Example | Message |
| Properties |
The Contract Negotiation Termination Message is sent by a [=Consumer=] or [=Provider=] indicating it has cancelled the [=Contract Negotiation=] sequence. The message MAY be sent at any state of a [=Contract Negotiation=] without providing an explanation. Nevertheless, the sender MAY provide a description to help the receiver.
-
The message MUST contain a
consumerPidand aproviderPid. -
If an error is received in response to the message, the sending party MAY choose to ignore the error.
Note that a [=Contract Negotiation=] MAY be terminated for a variety of reasons, for example, an unrecoverable error was encountered or one of the parties no longer wishes to continue. A [=Connector=]'s operator MAY remove terminated [=Contract Negotiation=] resources after it has reached the terminated state.
The ACK and ERROR response types are mapped onto a protocol such as HTTPS. A description of an error MAY be
provided in protocol-dependent forms, e.g., for an HTTPS binding in the request or response body.
| Sent by | [=Consumer=], [=Provider=] |
| Schema | JSON Schema |
| Example | Process |
| Properties |
The Contract Negotiation is an object returned by a [=Consumer=] or [=Provider=] indicating a successful state change happened.
An [=Agreement=] contains the following attributes:
-
An Agreement MUST be associated with exactly one [=Dataset=].
-
An Agreement MUST include exactly one
targetattribute that is the identifier of the [=Dataset=] the [=Agreement=] is associated with.
| Sent by | [=Consumer=], [=Provider=] |
| Schema | JSON Schema |
| Example | Error |
| Properties |
The Contract Negotiation Error is an object returned by a [=Consumer=] or [=Provider=] indicating an error has occurred. It does not cause a state transition.
