New location: aries-rfcs/concepts/0020-message-types
0021: Message Types¶
Authors: Daniel Bluhm daniel.bluhm@sovrin.org, Sam Curren sam@sovrin.org
Start Date: 2018-07-06
Status¶
Status: SUPERSEDED
Status Date: (date of first submission or last status change)
Status Note: (explanation of current status; if adopted, links to impls or derivative ideas; if superseded, link to replacement)
Summary¶
Define structure of message type strings used in agent to agent communication, describe their resolution to documentation URIs, and offer guidelines for type family specifications.
Motivation¶
A clear convention to follow for agent developers is necessary for interoperability and continued progress as a community.
Tutorial¶
A “Message Type” is a required attribute of all communications sent between parties. The message type instructs the receiving agent how to interpret the content and what content to expect as part of a given message.
Types are specified within a message using the @type
attribute:
{
`@type`:<message type string>,
// other attributes
}
We propose that message types are ledger resolvable DIDs with an endpoint specifier and path:
did:<method>:<id-string>;<service>/<message_family>/<major_family_version>.<minor_family_version>/<message_type>
Example DID and DID Document for Message Type Specification¶
The following was taken from a presentation by Drummond Reed during the Agent Summit. A link to this presentation can be found below in the Reference section.
Problem¶
How to use a DID to identify a digital object that:
Can be widely referenced.
Is cryptographically verifiable.
Is human readable enough for developers.
Solution¶
Use a full DID reference that contains a service name and path.
Example DID Reference¶
This DID reference contains a service name (;spec
) followed by a path that expresses the semantics of an example message type family.
did:sov:123456789abcdefghi1234;spec/examplefamily/1.0/exampletype
Example DID Document¶
This example DID document shows a service endpoint that includes a name property (emphasized) whose purpose is to enable creation of DID references that can deterministically select that service in order to have an algorithmic transformation into a concrete URI.
{
"@context": "https://w3id.org/did/v1",
"id": "did:example:123456789abcdefghi",
"publicKey": [{
"id": "did:example:123456789abcdefghi#keys-1",
"type": "RsaSigningKey2018",
"owner": "did:example:123456789abcdefghi",
"publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
}],
"authentication": [{
"type": "RsaSignatureAuthentication2018",
"publicKey": "did:example:123456789abcdefghi#keys-1"
}],
"service": [{
"type": "Document",
"name": "spec", // <--- Name property
"serviceEndpoint": "https://sovrin.org/specs/"
}]
}
Resolution Process¶
This is the full ABNF for a DID:
did-reference = did [ ";" did-service ] [ "/" did-path ] [ "?" did-query ]
[ "#" did-frag ]
did = "did:" method ":" specific-idstring
method = 1*namechar
namechar = %x61-7A / DIGIT
specific-idstring = idstring *( ":" idstring )
idstring = 1*idchar
idchar = ALPHA / DIGIT / "." / "-"
did-service = 1*servchar *( ";" 1*servchar )
servchar = idchar / "=" / "&"
The purpose of the did-service
component that may optionally follow a DID is to enable construction of a DID reference that may be algorithmically transformed into a concrete URL to access the target resource. There are two algorithms for this transformation. Both begin with the same first step:
Extract the DID plus the
did-service
component from the DID reference. Call this the DID service locator. Call the rest of the DID reference theservice-specific
string.
Service Selection by ID¶
This algorithm MUST be used if the did-service
component does NOT begin with the string type=
.
Select the first
service
object whose id property contains an exact match to the DID service locator.Select the
serviceEndpoint
property of the selectedservice
object.Extract the value of the
serviceEndpoint
property. Call this the endpoint URL.Append the service-specific string to the endpoint URL.
The final result is the concrete URL.
Example¶
The following agent message is received with a type not known to the developer:
{
'@type': 'did:sov:123456789abcdefghi1234;spec/examplefamily/1.0/exampletype',
'attr_a': 5,
'attr_b': 'Gouda'
}
The @type
is extracted, with a DID reference that resolves to the example service
block above:
did:sov:123456789abcdefghi1234;spec/examplefamily/1.0/exampletype
A DID resolver would algorithmically transform that DID reference to the following concrete URL:
https://sovrin.org/specs/examplefamily/1.0/exampletype
The developer would then be able to load this URL in a browser to discover the meaning of attr_a
and attr_b
.
Indy Core Message Namespace¶
did:sov:BzCbsNYhMrjHiqZDTUASHg
will be used to namespace message families defined by the community as “core message families” or message families that agents must minimally support.
This DID is currently held by Daniel Hardman. Ownership will be transferred to the correct entity as soon as possible.
Message Families¶
Message families provide a logical grouping for message types. These families, along with each type belonging to that family, are to be defined in future HIPEs or through means appropriate to subprojects.
Family Versioning¶
Version numbering should essentially follow Semantic Versioning 2.0.0, excluding patch version number. To summarize, a change in the major family version number indicates a breaking change while the minor family version number indicates non-breaking additions.
Message Type Design Guidelines¶
These guidelines are guidelines on purpose. There will be situations where a good design will have to choose between conflicting points, or ignore all of them. The goal should always be clear and good design.
Respect Reserved Attribute Names¶
Reserved attributes are prefixed with an @
sign, such as @type
. Don’t use this prefix for an attribute, even if use of that specific attribute is undefined.
Avoid ambiguous attribute names¶
Data, id, and package, are often terrible names. Adjust the name to enhance meaning. For example, use message_id
instead of id
.
Avoid names with special characters¶
Technically, attribute names can be any valid json key (except prefixed with @, as mentioned above). Practically, you should avoid using special characters, including those that need to be escaped. Underscores and dashes [_,-] are totally acceptable, but you should avoid quotation marks, punctuation, and other symbols.
Use attributes consistently across message families¶
Be consistent with attribute names between the different types within a message family. Only use the same attribute name for the same data. If the attribute values are similar, but not exactly the same, adjust the name to indicate the difference.
Nest Attributes only when useful¶
Attributes do not need to be nested under a top level attribute, but can be to organize related attributes. Nesting all message attributes under one top level attribute is not usually a good idea.
Design Examples¶
Example 1
{
"@type": "did:example:00000;spec/pizzaplace/1.0/pizzaorder",
"content": {
"id": 15,
"name": "combo",
"prepaid?": true,
"ingredients": ["pepperoni", "bell peppers", "anchovies"]
}
}
Suggestions: Ambiguous names, unnecessary nesting, symbols in names.
Example 1 Fixed
{
"@type": "did:example:00000;spec/pizzaplace/1.0/pizzaorder",
"table_id": 15,
"pizza_name": "combo",
"prepaid": true,
"ingredients": ["pepperoni", "bell peppers", "anchovies"]
}