A contract in the world of computer science is something that defines what the inputs and outputs of a given function are allowed to be, and what you can expect to get as outputs when you hand over a certain set of inputs. This concept is fundamental to APIs, libraries, languages, protocols, and basically all portions of the technology world.
But the most important thing about contracts is that they allow you to fulfill the contract in whatever way you want to. As long as you’re abiding by the contract’s guides, you can do whatever makes the most sense within your platform, deployment, and implementation parameters. This provides an abstraction layer that the rest of the system can depend on. From the outside world, might as well look like this:
The contracts of functions define how to interface with their balls of magic. If you’ve defined things right, that bit of magic won’t make much of a difference, and you could even swap out that particular magic for some other piece of magic that works the same way and things would be fine. The problem is defining exactly how you can expect that magic to work. This is both vitally important and notoriously difficult in practice.
DID or DID-not
Over the last year I’ve gotten involved in the distributed identifier (DID) community. There’s a working group in the W3C that’s trying to standardize how DIDs work, including how the DID itself is formatted and what is in the resource the DID points to — called a DID document. There are all kinds of parts of the DID that can help determine which DID document to point to, and all kinds of bits inside the DID document that allow to you do some useful things. There’s a process called DID resolution that’s meant to connect these two, using a DID method. All together, these components make a nice technology sandwich.
However, there’s something else about the DID community: it’s made up of a bunch of different companies and groups that are working on their own proprietary solutions for the resolution process. Some are using distributed ledgers, some are using cloud-backed systems, some are using IoT-driven distributed data, among other clever designs. On its own, this isn’t really a problem — the diversity of a community can be one of its strengths. There is a huge variety in how people want to define a DID method’s internal workings, and that’s one of the things that makes it an interesting space. This kind of flexibility has been built into the design of the whole system from the start, as well, and so people expect to be able to do some bit of proprietary dazzle in the middle of the process no matter what the standard defines. Members of the community are highly motivated to protect their proprietary stacks.
The problem comes with the fact that, at this time, the DID core specification defines only the endpoints: the DID itself and the DID document. So how do you take a DID and make it into a DID document? Magic, probably. This issue comes into stark contrast when you realize that the DID is the input and the DID document is the output to that bit of magic. Everyone wants to agree on what the inputs and outputs are, but so far there isn’t any agreement on what kinds of behaviors are allowed and expected in between the two. This gap has led to conflicting requirements on either end of the stack, since people have different ideas on where exactly the boundaries lie between what’s being standardized and what’s allowed to vary in a proprietary system.
It’s a sandwich made of bread and magic right now, and we need to do better than that if we want to succeed.
To that end, Markus Sabadello and I have proposed a set of contracts for the DID community. These contracts, or something much like them, are needed to define the process of going from a DID to its attendant DID document. Importantly, they don’t say anything about how you get there. But they do name the functions available and provide structures for inputs and outputs that had previously been hand-waved through the community. These input and output structures give us places to put things that had previously been jammed into the DID and DID document. It wasn’t that this was necessarily a good fit, but simply that there was no other community-defined input space than the DID and no output space but the document, and so everything has to go there if it goes anywhere at all.
At the time of this writing, these changes aren’t in the spec yet, but in my opinion, they need to be in order for this to be workable. Nobody wants a sandwich if you can’t tell where the bread ends and the magic begins. But this is one of the things that makes the standards world fascinating to me. Programming engineers is really difficult and often frustrating, but it’s certainly interesting and can be really rewarding.