json-schema-org / json-schema-spec

The JSON Schema specification
http://json-schema.org/
Other
3.83k stars 266 forks source link

Does anyone actually use JSON Hyper-schema #48

Closed awwright closed 8 years ago

awwright commented 8 years ago

There's a lot of broken features defined in JSON Hyper-Schema, I want to ask implementors how much I can be allowed to "break" (i.e. make compliant with normative references).

Mostly things like quirks about how it defines URI templates, uses "rel", and uses "method".

Anyone?

handrews commented 8 years ago

@jdesrosiers Hmm... maybe I shouldn't have used "classes". I really, truly, do not think of REST APIs in terms of OO. They are fundamentally different paradigms. I'll have to think more on how to convey this better. All I really mean by "class" here is that "all of these resource instances, as defined by the template self link, behave the same way." But REST behavior and OO behavior are not the same sort of thing, so "class" is misleading. I dislike "type" even more. Resources aren't types. Resource family? Open to suggestion here.

Also, you said:

I wouldn't [figure out the set of resource families in the system]. The authoritative reference on what relations a resource has is the resource itself. A REST system has a reactive and dynamic quality to it. Documenting the system as a whole doesn't make sense to me. You learn about the system by browsing it. Each resource you get has it's own documentation.

Yes, resources in a RESTful system inform clients what their relations are. They do this in ways that are media type and/or protocol specific, such as using link and anchor tags in HTML, or xlink in XML. When using HTTP, link headers can be used.

JSON does not have a mechanism for links. That is the point of JSON Hyper-Schema. The way a resource that is represented through JSON advertises its links is by providing a schema.

So I don't see the point of saying that a hyper-schema system that is built to describe links for JSON representation should not be used to describe links for a JSON representation. Am I missing something here? In this case, I don't mean whether the resource supports GET/PUT/whatever, I mean which other resources are linked to this resource. HTTP link headers are inadequate to convey all of the ways to fill out a complex URI template such as for a filtering system. Again, that's part of the point of Hyper-Schema.

If we're not relying on hyper-schema to describe hyperlinks, what are we doing with it?

awwright commented 8 years ago

@handrews For any problems you can identify with JSON Hyper-schema, I would strongly encourage you to file an issue describing the problem. Discussion here is fine too, but all the questions and responses I'm posing here are aimed at answering the question I opened this issue specifically to ask.

I'm afraid the definitions used so far are more complex than they need to be, let me put forward these definitions:

awwright commented 8 years ago

We do have an IRC channel, see http://json-schema.org/ for details.

jdesrosiers commented 8 years ago

@handrews, wow. you really misunderstood. Earlier I said,

it helps to think of the analogy to HTML as the JSON document + the Hyper-Schema.

That was what I meant when I talked about a resource. It's like how you don't think of a webpage as just HTML; it is also CSS, JavaScript, and images. It was perhaps a little sloppy use of language on my part, but I didn't want to confuse the concept with technicalities. That didn't work out as I hoped.

Even though a JSON document is a resource and a Hyper-Schema is a resource, in this context one is not complete without the other. I'll call this combination a "hyper-json" in order to stop using the term resource because it is apparently misleading. Hyper-jsons are the units that make up the APIs that I write. A hyper-json has no URI Templates because the Hyper-Schema URI Templates have all been evaluated to a concrete URI based on the JSON document it was paired with. These hyper-jsons are what make up the API. Hyper-Schemas are just templates and by themselves don't fully describe the API.

In order to get the kind of information you are talking about, you would have to crawl the API just like you would crawl a website.

awwright commented 8 years ago

I've made updates to JSON Hyper-schema in HEAD/master with the feedback here. I don't think it's reasonable to remove too much in the way of functionality, or add any functionality, and I figured out much of the current draft can be ironed out more smoothly:

The "method" section now looks like:

5.6.1. method

This property specifies that the client can construct a templated query or non-idempotent request to a resource.

If "method" is "get", the link identifies how a user can compute the URI of an arbritrary resource. For example, how compute a link to a page of search results relating to the instance, for a user-selected query term. Despite being named after GET, there is no constraint on the method or protocol used to interact with the remote resource.

If "method" is "post", the link identifies how a user can construct a JSON document to submit to the link target for evaluation.

handrews commented 8 years ago

@jdesrosiers

That didn't work out as I hoped.

LOL I think that has been true for each of us in this discussion a few times! Just in case it is not coming across in my writing, I am very appreciative of all of the discussion, opinions, and ideas, and am really enjoying how everyone is being so constructive. I hope my contributions come across that way even when careening off the rails :-)

In order to get the kind of information you are talking about, you would have to crawl the API just like you would crawl a website.

That's kind of my point- while if you want to find every concrete resource in the API, of course you have to crawl it. Hyper-schema will never tell you how many member resources are present in a collection resource, for instance.

But at the abstract level (what I was calling resource families) you don't need to walk over anything. Most HTTP APIs document these things be giving them a name, documenting the URI template, all of the methods and requests and responses, etc. This, to me, is a REST anti-pattern, because the exact URIs (or templates) are not something clients should get from documentation. They should be getting those through HATEOAS. Most APIs relegate far too much information to documentation.

But there is a vocabulary to a given REST API. Your client (human or otherwise) needs to know the names of the entities (resources and important fields) and the names of the relations among the entities. REST documentation should focus on this vocabulary. It is the part of the API that a human must comprehend in order to use the API, either by browsing or by writing a program. Some of the vocabulary can come from standards, but some will be domain (API) specific.

I am trying to figure out how I can read the hyper-schemas for an API and generate this sort of documentation instead of documenting a pile of URI templates and HTTP methods, requests, and responses. In the somewhat-regretted example that I put up, "network" and "uplink" are part of the vocabulary. There are no IANA-registered relations to explain how those two things fit together.

There must be some sort of documentation that tells client developers that this API deals with "network" and "uplink", and that makes it clear what those English words mean in the context of the API. The documentation should not get into the details of URI construction- that should be driven by what you call the hyper-json. But somehow I have to know that if I want to do stuff with networks and uplinks, this is the API that I use. And I have to know what relation to follow from the entry point resource to start, as there are no standard relations for these things. And I need to know what the representation of each of those concepts looks like (because once I know that, HTTP tells me a lot about where in various requests and responses I should use or expect to see that representation).

Perhaps another way to approach this discussion is to ask: What does your ideal REST API documentation look like? And what role do you see for hyper-schema in producing that documentation?

To recap, my ideal documentation names each resource family (or class or type or whatever we're calling it), describes its representation, and names the link relations that connect the various resource families to each other. Of course in practice, links connect specific resource instances to each other, but even though there are many instances of "network" and "uplink", we still just document what "network" and "uplink" mean once.

My ideal documentation does not publish URI templates or document the specifics of HTTP usage. It does need to include documentation of things like how to think about interactions that are not standardized, e.g. HTTP POST interactions other than those that create resources. It does need to document possible error resources (i.e. error response bodies as covered by the JSON Problem RFC- the codes are documented by HTTP), which is a critical topic of APIs which we have not even begun to discuss.

I've not yet seen any documentation of this sort (the docs generated from the Riverbed hyper-schema alternative still had way too much URI and HTTP information in them for my tastes, and not enough about error responses, but I lost that battle).

handrews commented 8 years ago

@awwright

This:

If "method" is "get", the link identifies how a user can compute the URI of an arbritrary resource. For example, how compute a link to a page of search results relating to the instance, for a user-selected query term. Despite being named after GET, there is no constraint on the method or protocol used to interact with the remote resource.

is a bad design smell if I've ever encountered one. If you just mean this as a clarification of the current state of things for Draft 05, I'm fine with it. But I think it's absolutely critical to separate methods (whether abstract or actual HTTP methods) from the definition of URI templates and the rules for filling them out from the representation. Any time your specification has to say "ignore this thing, it doesn't mean what it appears to me" then you have an unsustainable mess on your hands.

I'll attempt to reconcile the various concept definitions after getting some sleep. Are you getting your terminology such as IR/NIR from existing standards? I will happily adopt broadly-accepted terminology and definitions.

awwright commented 8 years ago

@handrews "Information Resource" and "Non-Information Resource" are formal terms used in Semantic Web technology, I don't believe there's a particular document that defines it all, but can be found in both formal and informal documents, e.g.:

You'll have to clarify what the design smell is, exactly.

I don't think the HTML design makes a lot of sense; but the way it's worded now not only preserves compatibility with existing implementations, but brings the definition into line with how HTML uses forms.

Even in HTML, method="get" and method="post" doesn't necessarily mean an HTTP operation using that method. Indeed, <form method="post" action="mailto:robot@example.com"> ... is supposed to send an email, not make an HTTP request.

"get" and "post" may have been unfortunate choices of vocabulary for us human's sake, but at the end of the day they're just words. For all a computer cares, it could have been called "foo" and "bar".

If you're talking about discovering how to interact with a remote server, again, links are only for discovering the existence of new resources. Interaction with them is defined by the protocol you use to talk to a server, and their media type, if they have one.

I've laid most of the arguments for this design out, and I believe this is the current state of the art in hypermedia systems, but if you have a specific counterargument or believe this is wrong I can certainly consider it.


As for RESTfulness, it's certainly true that prose defining URI templates is not RESTful. In my understanding, servers can still provide clients with URI templates, however, and they can even cache these URI templates and use them within the expiry lifetime. The distinction is that for the latter case, the server always retains control of its namespace.

Leonard Richardson is the biggest pioneer of this concept, see https://www.infoq.com/presentations/REST-Hypermedia-Links-Forms for his wonderful explanation of this.

You probably knew this already, but it's worth stating explicitly.

awwright commented 8 years ago

There's one more thing I have to say here for the record just because I don't want to forget it:

Links on the Web follow the concept of progressive disclosure: The links that are shown are only the ones relevant to the resource they appear on. If a resource has been locked for editing, it does not make sense to provide a rel="edit-form" link.

We should examine how JSON Hyper-schema inhibits, if at all, progressive disclosure on the Web.

handrews commented 8 years ago

@awwright

I think we still need to be more clear on splitting the concept of discovering (and identifying) resources from describing any part of what operations can be done with the discovered resource.

First let me clearly align my terminology with yours (hopefully):

In the Riverbed hyper-schema alternative example, the resources section is (generally) how a client discovered new resources. The "self" link is how resources are identified (URI construction). The other entries in the links section describe operations on the resource (whether that is a good idea or not is still an open question). There is a notable problem which is that the keys in both resources and links are link relation names, which I think muddles the concepts considerably and has led to some of the major confusion.

Having explained all of that, let me definitively discard that terminology. I am on board with "links are only for discovering the existence of new resources." The "self" link also identifies resources using a given schema through specifying how to construct URIs. This is true both in Draft 04 hyper-schema and in the Riverbed format, so I think we're in agreement on that part. If you don't think that's a good way to think about the "self" link, please let me know of a better conceptual model.

So I'm fine with specifying links in that sense of "only for discovering of new resources." But I still have concerns around specifying operations. Currently this is handled by some combination of indicating a method of "get" or "post" in the LDO, and/or deferring to the protocol.

If links are only about finding resources, expressing any operation as part of the LDO at best distracts from that definition of links, and at worst is totally conceptually wrong.

I think we can all agree that HTML is not a good role model for more general hyperlinking. @awwright , you earlier said:

it appears the functionality was copied from HTML, even though it's a poor design and not really suitable for hypermedia in general.

Forms in HTML serve the purpose of both URI generators and remote execution. If you want to tell a person how to jump to page n in a paginated list, you use an HTML form with method="GET". On the other hand, if you want to tell a person how to create a new resource in a collection, you use an HTML form with method="POST". They're two totally different things, and they probably should have been entirely different HTML tags.

I think JSON Schema is sort of making the same mistake. There's no need to specify "method".

We're in agreement here (I think), which is why I am confused by the continued references to HTML to justify anything. Associating method with links is propagating HTML's problems into an area that has no need for it. Even in HTML, the <link /> element does NOT specify or imply a method. If we're going to follow HTML, this is what we should follow, not the anachronistic behaviors of <a></a> and <form></form>.

So again, if this wording is just to clarify the current behavior, that's fine- obviously we can't toss method and preserve compatibility. But if we're looking ahead, method should not be in the LDO at all. I can't tell from your reply whether you are advocating for continuing with this approach or just clarifying for the immediate next draft- if you could state which it is that would be help me with this a lot.

The "design smell" is the fact that specifying some particular method ("get") is supposed to be interpreted as not specifying an actual method, but just indicating that the link tells you how to get the URI of the related resource.

I'm not complaining about whether "get" indicates an HTTP GET or not. I'm fine with the values of method (wherever it lives in whatever form) being non-protocol-specific so that we can defer the specifics to the protocol (more on that later). It doesn't seriously bother me that the non-protocol-specific values happen to match two of HTTP's methods. That's probably not ideal, but it's waaaaay down on my list of concerns.

I'm complaining that a keyword called method is sometimes used for something other than defining a method. Basically, "post" does indicate that a method (specifically some protocol-determined non-idempotent method) is supported, but "get" does not say anything about method support. Let's just separate any description of methods/operations from the identification of related resources.

I'm going to address issues around deferring the specifics of interactions to the protocol in a separate comment, as they're orthogonal to the concerns in this comment.

awwright commented 8 years ago

@handrews Understood... I think. Let's open this on a new issue to re-examine for draft-06. Because no matter what this still needs work.

And let us know there if you think we've satisfactorily addressed the conserns well enough to release draft-05 that's supposed to be reverse-compatible.

handrews commented 8 years ago

@awwright will do, thanks. I will go over draft-05 and provide comments as soon as I finish responding to the last 24 hours' worth of activity :-)

handrews commented 8 years ago

Earlier I said:

I'm going to address issues around deferring the specifics of interactions to the protocol in a separate comment, as they're orthogonal to the concerns in this comment.

Nearly all of that is covered under issue #88 "problems" with relying on delegating to the protocol only really occur when the protocol is being abused. Which is very common with HTTP APIs.

handrews commented 8 years ago

@awwright

As for RESTfulness, it's certainly true that prose defining URI templates is not RESTful. In my understanding, servers can still provide clients with URI templates, however, and they can even cache these URI templates and use them within the expiry lifetime.

I definitely never intended to associate prose-defined URI templates with RESTfulness! Documenting a real REST API's URI templates is anti-RESTful. REST documentation should focus on the API's vocabulary rather than URI construction (or most other things that people tend to put in HTTP API documentation).

Relequestual commented 8 years ago

What's required to close this issue?

awwright commented 8 years ago

I was going to close this, I forget why I didn't, I think I was waiting on something. But this is answered to my satisfaction now.

handrews commented 8 years ago

Pretty much all of my concerns have been addressed by splitting off #88 and #89, plus the other stuff that @awwright asked me to file separately which is in my increasingly large stack of partially written proposals. So I don't have any major outstanding concerns either.

Relequestual commented 7 years ago

@jdesrosiers Sorry to dig up an old issue, but regarding https://github.com/json-schema-org/json-schema-spec/issues/48#issuecomment-252394587 (and having not re-read the full issue comments):

JSON Hyper-Schema is the only Level 3 option around.

I'm all for supporting JSON Schema (heck, I'm putting a lot of time into working on it!), but I recently read http://www.foxycart.com/blog/the-hypermedia-debate#.WMZyHBARDPc - Does that article not suggest 3 other standards which can attain RMM Level 3? Also, JSON-LD? I think I'm just starting to better understand Hyper Schema and HATEOAS, so trying to feel out what other people who have been doing this already feel.

jdesrosiers commented 7 years ago

@Relequestual, I'm a little more strict about what I consider RMM Level 3 than the general community. To explain, I'll introduce the Desrosiers Maturity Model (DMM) for Hypermedia APIs :-). Like the RMM, the lower levels incorporate only the most basic concepts. Based on the DMM scale, the general community seems to be accepting of anything Level 1 or higher, while my statements were inclusive of Level 2 or higher.

The general concept is that responses should be self-descriptive. Like an HTML browser, it should be possible to navigate a Hypermedia API without any out-of-band documentation. The levels go from more documentation needed to less.

Level 0: At this level, a representation would include URIs referencing another resource, but they are just strings with no semantics allowing a machine to recognize it as a link and processes it as such. To a computer, these URIs are just strings. Documentation is needed to know that these links should be followed. This is like not having a <a> tag in HTML. You can have the URIs text on the page, but you have to follow them manually.

{
  "id": 23,
  "title": "My Blog Post",
  "content": "...",
  "author": "/api/author/1",
  "comments": "/api/blog/23/comments"
}

Level 1: The next step is to use a media type that defines link semantics allowing a computer to recognize it as a link. This is like having an <a> tag in HTML. A user agent can now follow these links to related resources. Level 1 is sufficient for read-only APIs, but is lacking when user input is required. If you need to send data to the server you have to describe in text how it should be done. This is like not having a <form> tag in HTML. HAL is Level 1.

Level 2: To be Level 2, you need to a hypermedia format that has a feature that resembles an HTML <form>. JSON Hyper-Schema has this ability and at the time I made the claim you quoted, I had not seen another option that did. Confession time. I took another look at Collection+JSON and Siren and saw that they do have this feature after all (Collection+JSON calls them templates and Siren calls them actions). I must have missed it in my previous evaluations. So, based on my own definition, I have to include them as options for achieving RMM Level 3. I saw another media type recently that would qualify as Level 2, but I can't find it now and don't remember what it was called.

Hyper-Schema is still my heavy favorite because of it's superior ability to describe request body requirements and it's simple and unobtrusive syntax. Collection+JSON only seems to be able to declare property names of the data you want to send. Siren goes one step further by allowing to specify a datatype. Both of these options are incredibly rudimentary compared to being able to describe the request body with a JSON Schema. Hyper-Schema wins big in that respect.

Level 3: Level 2 is sufficient for most APIs, but it is possible to take things even further. Just like how we said in Level 0 that a URI is just a meaningless string to a computer, property names like "title" or "author" also have no meaning either. If your data is self-descriptive, you now have the possibility of automating things like interactions between systems where it usually requires a human to hard-code the connecting points. A form could be filled in automatically because the computer knows how the data it has matches up to the form data being requested. This can be achieved using JSON-LD in conjunction with a Level 2 hypemedia format.

There is a format called Hydra that is based in JSON-LD, but I don't think there is any reason why JSON-LD responses couldn't be used with any of the other Level 2 formats mentioned to the same effect. However, Hydra is the only hypermedia format I know of that is Level 3 without having to be combined with anything else. That said, I'm not a fan of Hydra. I found it to be way more complicated than it needs to be and soon went back to simple and unobtrusive Hyper-Schema.

So, in conclusion, I was wrong that there aren't any other options out there, but I still think JSON Hyper-Schema is easily the best option.

handrews commented 7 years ago

@jdesrosiers thank you for the thorough response- great stuff!

I met Gregg Kellogg, one of the editors of the JSON-LD spec, at a W3C Web of Things conference recently, as the W3C WoT group is using a combination of JSON Schema and JSON-LD and invited each of us to discuss our respective (proposed) standards. There was a consensus that JSON-LD and JSON Schema Validation are solving different problems and that it would be good to at minimum work out some best practices for combining them. And probably do some work to make them easier to use together. I haven't followed up on this yet, but I will do so after Draft 06 is out the door.

I also evangelized Hyper-Schema a good bit, and there was some interest. Gregg brought up Hydra, but he's not much involved in it so there was no one there as a strong advocate for it. I've since read up on it, and I prefer our approach, even for Hyper-Schema + JSON-LD. Hydra is very focused on HTTP APIs and operations (exact HTTP requests/responses/methods/errors), rather than on defining links and letting the link relation and the protocol from the URL scheme determine possible operations.

Hyper-Schema does still needs a hints mechanism for things like HTTP Allow and Accept-Patch, but as of Draft 06 I think it's well-positioned to be usable in a system that discovers everything at runtime. To me, that is an essential difference: we (will eventually once again) treat HTTP usage specifics as an optimization, but allow the full runtime use of the protocol in a much more generic sense.

If your data is self-descriptive, you now have the possibility of automating things like interactions between systems where it usually requires a human to hard-code the connecting points. A form could be filled in automatically because the computer knows how the data it has matches up to the form data being requested. This can be achieved using JSON-LD in conjunction with a Level 2 hypemedia format.

This is the sort of thing I mean by clarifying how to use JSON-LD in conjunction with JSON Hyper-Schema :-)

Automating the connecting points is what #108 is all about. Some of that has now been implemented in Draft 06, and I might need to update and/or split what remains. But assuming we solve every use case (by whatever mechanism) then we will be fully capable of this sort of fully automated interactions.

Of course Internet/Web of Things people are much more interested in this than web app authors who have a couple of resources that are always used by programs encoding a specific simple workflow. IoT devices need a lot more flexibility and autonomy, so I suspect that community will drive a lot of "DMM Level 3" work.

Relequestual commented 7 years ago

Thanks for your replies @jdesrosiers @handrews

Just to calrify, because I'm a little unsure, but are you guys saying that you're including HyperSchema key words in your return json?

Unrelated to my question but in relation to your comments: I was going to email you @handrews at some point soon to show you I'd found an example of someone using JSON Schema and JSON-LD, and I wasn't really sure what was going on. Interesting none the less. It's good we have open communication lines. I'm going to try and expand these to comapnies in the near future.

jdesrosiers commented 7 years ago

@handrews, it's great to hear that you are out there evangelizing Hyper-Schema. So few people seem to even realize that it exists. I never see it mentioned in discussions about Hypermedia APIs.

I'm very interested in better understanding how to use JSON-LD with JSON Hyper-Schema. I should admit that at this point DMM Level 3 is just theoretical to me. I have no practical experience with this yet and I don't know what it's limitations might be. I hope to be able to spend some time digging into this at some point.

@Relequestual, Hyper-Schema keywords are included in the JSON Schema, not the response body. In that way it is unique from other hypermedia formats. Check out this thread, https://groups.google.com/forum/#!topic/json-schema/40-rl7QKtiM. I think that should help explain how it works.

handrews commented 7 years ago

@jdesrosiers I should have a public blog post at my day job soonish that starts to explain how we're going to approach hypermedia. We'll also be building an open source generic hypermedia API client (initially in JavaScript, most likely).

I came close to DMM Level 3 in my work at Riverbed , which was Hyper-Schema-inspired rather than actual Hyper-Schema (long story, not relevant to future work). But we did actually use the sleepwalker.DataRep class that I linked to to automatically pull data from the current resource to construct the URI for the next resource. The only piece that was missing was the ability to pull data from the current resource to construct all or part of the request body for the next resource. Which is what I talk about in #108, and what I plan to do (hopefully with Hyper-Schema) for my current API work.

handrews commented 7 years ago

@Relequestual I include Hyper-Shema keyword in the response schemas, but not in the response instance data. That lets me use links from the response document, without the links appearing inline in the response.

handrews commented 7 years ago

@Relequestual actually it's more accurate that I define a resource's representation, including its links, under "definitions" and then always "$ref" that schema everywhere its needed, including requests and responses. This means that the links are always present wherever the representation is referenced.

So something like this, where I define a collection resource, an item resource, give them both "self" links and the appropriate side of the standard "collection" and "item" links, and use a custom link to connect the entry point to the collection:

{
  "definitions": {
    "identifier": {
      "description": "32-character hash identifier",
      "type": "string",
      "minLength": 32,
      "maxLength": 32,
      "pattern": "[0-9a-f]+"
    },
    "foo": {
      "$id": "#foo-item",
      "type": "object",
      "properties": {
        "id": {"$ref": "#/definitions/identifier"}
      },
      "links": [
        {
          "rel": "self",
          "href": "/foos/items/{id}",
          "hrefSchema": {
            "type": "object",
            "properties": {
              "id": {"$ref": "#/definitions/identifier"}
            }
          },
          "targetSchema": {"$ref": "#foo-item"}
        },
        {
          "rel": "collection",
          "href": "/foos",
          "targetSchema": {"$ref": "#foo-collection"},
          "schema": {"$ref": "#foo-item"}
        }
      ]
    },
    "foos": {
      "$id": "#foo-collection",
      "type": "array",
      "items": {
        "allOf": [
          {"$ref": "#foo-item"},
          {
            "links": [
              {
                "rel": "item",
                "href": "/foos/elements/{id}",
                "targetSchema": {"$ref": "#foo-item"}
              }
            ]
          }
        ]
      },
      "links": [
        {
          "rel": "self",
          "href": "/foos",
          "targetSchema": {"$ref": "#foo-collection"},
          "schema": {"$ref": "#foo-item"}
        }
      ]
    }
  },
  "link": [
    {
      "rel": "tag:example.com,2017:foos",
      "href": "/foos",
      "targetSchema": {"$ref": "#foo-collection"}
    }
  ]
}
Relequestual commented 7 years ago

Hyper-Schema keywords are included in the JSON Schema, not the response body. @jdesrosiers

Thanks, that's what I though. I was pretty sure that was the case, but some of the discussion here confused me.

Relequestual commented 7 years ago

I include Hyper-Shema keyword in the response schemas, but not in the response instance data. That lets me use links from the response document, without the links appearing inline in the response.

@handrews

I'm not sure I totally understand the phrasing you've used there, but I'll paraphrase what I understand when in conjunction with your example and you can tell me if I'm getting it or not.

You include the collection and single link in both the collection and single definitions, so it's clear how to get from one to another. Cross referencing them in a sense. Right?

My only query from that schema is what you're trying to imply by having...

          "targetSchema": {"$ref": "#foo-collection"},
          "schema": {"$ref": "#foo-item"}

schema key word is about payload, right? Are you trying to imply that that URL is for both getting the collection of items, but also for posting / creating a new individual items? I would expect (and have done for my schemas to work with doca) define two seperate link elements for getting and posting, specifying the method.

Maybe this conversation should be taken sideways into email... Breaking my own rule of clogging up an issue... but it's a closed one so not so bad I guess.

handrews commented 7 years ago

@Relequestual @jdesrosiers I realized I did part of the example wrong. The "item" link should be from each item within the collection, not from the top level of the collection. That should make a lot more sense :-)

@Relequestual: On the collection resource's self link, and the item resource's collection link, "targetSchema" is the collection. So if you GET on that link, you get the collection. If you PUT, you need to PUT the entire collection (unusual, but there are use cases for it and a collection is just another resource anyway).

On the item's self link, and each collection element's item link, "targetSchema" is the individual item resource. That's what you GET or PUT. Or PATCH, but that's a bit more complicated so I'm ignoring it for now. Let's get clear on the rest of it first.

On the item's collection link, and the collection's self link, "targetSchema" is the collection. Again, you GET and PUT that. But "schema" is the item.

An IANA "collection" link relation implies that a POST to the resource of an item representation will create a new item. While not mandated by the collection/item link relation RFC, this collection usage is basically the only design convention that's universally agreed-upon in all interpretations of "REST". An API should document that it does indeed support that, but this hyper-schema tells you everything you need to know to understand this.

The collection's "self" link has the same "schema" for the same reason, although at the "self" link relation does not determine anything about how POST is used. You need to notice that the "schema" schema has a "collection" relation that points back to yourself. Or notice that your "item" links points to the same thing as the "schema" schema. This is where things get a bit dodgy, and we need to put in more work. It needs to be fairly easy to recognize this sort of thing, but right now it's not entirely clear how that should work.

jdesrosiers commented 7 years ago

@handrews, it looks like we take somewhat different approaches. Your example looks like a service definition approach to me because you have everything defined in one big hyper-schema. What schema do you link to when someone requests a single foo? Do you duplicate #foo-item? Or, does it always refer back to the entry point schema somehow?

Below is how I would refactor your example to align with my approach. Each resource has a hyper-schema that applies to it. You might notice that I took out all uses of targetSchema. The reason I did that is because if it is a self link, it is understood that the targetSchema is the current schema. The explicit recursive reference is redundant.

  1. A request to api.example.com/ is described by the following hyper-schema. It defines a link to /foos.

    {
    "link": [
    {
      "rel": "tag:example.com,2017:foos",
      "href": "/foos"
    }
    ]
    }
  2. If the /foos link is followed, then a collection resource is returned and is described by the following hyper-schema. It defines a self link which can be used with GET, PUT, or DELETE where the targetSchema is understood to be this schema. It also defines a create link for adding a new foo. Because this schema references the foo-item schema, it has those links as well, including a link retrieve an individual foo.

    {
    "$id": "http://api.example.com/schemas/foo-collection",
    "type": "array",
    "items": { "$ref": "/schemas/foo-item" },
    "links": [
    {
      "rel": "self",
      "href": "/foos",
    },
    {
      "rel": "create",
      "href": "/foos",
      "method": "post",
      "schema": { "$ref": "/schemas/foo-item" }
    }
    ]
    }
  3. If an individual foo is requested from a /foo/elements/{id}, it is described by the following hyper-schema. This includes the multipurpose self link as well as a link to the collection it belongs to. If the user follows the collection link, they go to part 2 where they have a collection and it's hyper-schema.

    {
    "$id": "http://api.example.com/schemas/foo-item",
    "type": "object",
    "properties": {
    "id": {
      "allOf": [{ "$ref": "#/definitions/identifier" }],
      "readOnly": true
    },
    "foo": { "type": "string" }
    },
    "required": ["foo"],
    "definitions": {
    "identifier": {
      "description": "32-character hash identifier",
      "type": "string",
      "minLength": 32,
      "maxLength": 32,
      "pattern": "[0-9a-f]+"
    }
    },
    "links": [
    {
      "rel": "self",
      "href": "/foos/items/{id}"
    },
    {
      "rel": "collection",
      "href": "/foos"
    }
    ]
    }

In case it wasn't clear, when I said "a resource is described by" I mean it has a Link header with rel describedby that can be dereferenced get a hyper-schema that can be applied to that representation (thus adding links to the response).

Relequestual commented 7 years ago

See, this is my problem. Just two people having different interpretations of what's expected by default. If it's not "well done" or unclear, then why leave it abigious when the spec allows you to be unabigious? I'll happily share my JSON Schema files when our API goes "live" to show you how I've done this, but as of right now I cannot share them.

handrews commented 7 years ago

@jdesrosiers There are a few things I just didn't convey well or did mistakenly:

I'll comment again in a bit about where I still see differences. I need to think through the points I want to make a bit more first.

handrews commented 7 years ago

@Relequestual I want to separate two different sorts of concerns:

  1. True hypermedia APIs are still not a well-understood thing, and designing them is challenging no matter your media types.
  2. JSON Hyper-Schema does not yet provide all of the tools necessary to implement a comprehensive hypermedia design.

The first set of problems are not things that we can or should solve as part of JSON Hyper-Schema. An example relevant here is that IANA-registered link relations are often intentionally under-specified so that they can be used in a very broad set of circumstances.

The most significant difference between my schemas and @jdesrosiers's is in the choice of link relation type and the positioning of the links. I'm making an argument about what sort of assumptions you can make based on the presence of the IANA-registered "collection" and "item" link relations, even though the RFC that defines those relations does not require those assumptions, and therefore does not guarantee that they will always be correct.

But that has nothing to do with JSON Hyper-Schema. We could use XML and still find ourselves debating whether "collection" and "item" convey all of the necessary information.

What might be relevant is a question of whether JSON Hyper-Schema (or XML, or whatever) has or should have a mechanism of disambiguating standard link relation usage. Or describing custom link relation usage. Which I think is where @jdesrosiers's Relation Description Object proposal is coming from. But that's not specific to the choice of "collection" and "item" alone vs using a "create" relation.

Once you split the ambiguity up like this, it becomes clear that it's not a fundamental problem with JSON Hyper-Schema. Figuring out what assumptions can be made for a given link relation is independent of media type. Specifying assumptions is potentially part of the media type, but not specific to these link relations. And the differences in approach here come down to choice of an under-specified standard link relation vs a fully specified custom link relation (albeit a highly intuitive one).

jdesrosiers commented 7 years ago

@Relequestual, I think the problem is that there are no tutorials out there showing how it is supposed to work. This is especially true of draft-05 which was a significant change. My approach has been shaped primarily by one principle: It has to work in the Jsonary browser. If I can't navigate the entire API just by following links and filling in forms, then I'm doing something wrong.

Here is the example we have been discussing as a simple static site http://hyper-foo.s3-website-us-west-1.amazonaws.com/?url=example.json. None of the unsafe methods are supported, but those links are defined so you can see it work. Also, the schemas are modified a bit because it only supports draft-04.

Jsonary was created by the creator of JSON Hyper-Schema, so I see it as the reference implementation for the standard (draft-04 at least).

jdesrosiers commented 7 years ago

@handrews, thanks for the clarification. It sounds like we are on the same page (or at least very close) after all.

handrews commented 7 years ago

@jdesrosiers yay! :-)

As I alluded to in the last comment, I think our difference is mostly about choosing which link relations to use and where to put them, and about how much we can assume from the presence of a particular link relation. While that's somewhat orthogonal to JSON Hyper-Schema itself, let me go into a bit more detail because I think the "create" relation in this case in part motivated by a weakness in Hyper-Schema as it currently stands.

In general, I avoid relations like "create" that are actions, because the relation type name should describe the nature of the relation between the resource, rather than directly specifying a thing you can do with the resource.

The important part of this is in avoiding having to specify one LDO per operation on the same target resource. This is where I think Draft-04 went wrong with its use of "method" to explicitly state the exact HTTP method. The use of the HTML-ish "get" and "post" without exactly meaning "get" and "post" was (in Draft-00 through -03) and is (in Draft-05 and -06) a problem, but that was not the correct solution. BTW I recently updated my detailed analysis and history of "method" in Hyper-Schema to cover Draft-06 and better cover Draft-05.

For any link with an HTTP URI scheme (with or without the -S, also CoAP or anything else with an explicit mapping to HTTP), a link indicates that the following are possible:

PATCH is more complicated as it should be expressed in terms of a patch media type, e.g. application/json-patch+json or application/merge-patch+json, and we don't have a good way to convey that right now.

We do not currently have an effective and well-designed way to express in Hyper-Schema how much of the above is actually supported, or if the resource behaves in any non-standard manners that violate these exceptions. A hit at the values of the "Allow" and "Accept-Patch" headers would fix a lot of that "Allow" would take a list of HTTP methods, to avoid duplication. If we had an "Accept-Patch" hint, or if clients did a HEAD to get the runtime "Accept-Patch", then the patch media type plus the "targetSchema" should tell us what we need to know, because patch media types tell us how to structure a patch for a given document.

This is why I do not think that Draft-04 or Jsonary are the right approaches. Both (along with nearly all documentation systems I have seen) are too operation focused. It's still leftover RPC. It should be resource-focused, and the possible operations are derived from the protocol indicated by the URI scheme. POST has no standard for describing its request format, so it is given explicitly. The only thing we are missing is a way to indicate design-time choices to disallow some methods/operations. Although...

Per RFC 5988, a link relation MAY specify that it implies certain operations (mapping to HTTP methods in this case) are or are not available. This is where I get the notion of assuming that a "collection" relation with a "schema" is telling me that I can create an item via that link. POST-to-create-in-collection is the only design pattern that is universally referenced by every guide to REST ever written. While the "collection" link relation RFC doesn't require it, I'd argue that anyone who violated that pattern in a RESTful API deserves whatever problems they get :-P

Note that not supporting creation and returning a 405 Not Allowed is fine. That's not violating the pattern, that's just opting not to implement it (a read-only collection). But specifying "schema" on a link with relation "collection" and having the associated POST do something else is just a horrible idea.

So where does that leave us? Well, I hope you can see why I am treating "collection" that way and not writing an explicit "create" relation, even if you don't find it compelling enough to adopt yourself. But mostly I agree with you that we lack tutorials and realty-tested best practices. For that, we just need to keep working on making this specification real, implemented, and running.

jdesrosiers commented 7 years ago

@handrews, I agree with almost all of what you say. Just two points where I disagree.

First, I don't share your concerns about the "create" relation. It looks like you are defining an action, but it can also be interpreted as defining a relationship to a resource that can be used to create something. Also, to be clear, this is the "create" relation that was defined in draft-04, not just some random description. However, I agree that "collection" could be used as well in this case. It may even be better. I'll have ponder that one a little longer.

But that brings me to the other point I disagree with: the idea that the "collection" link can be expressed as a single LDO. How schema is interpreted depends on the value of method. Without a value for method, the behavior of schema is undefined. You could do this ...

{
  "rel": "collection",
  "href": "/foos",
},
{
  "rel": "collection",
  "href": "/foos",
  "method": "post",
  "schema": { "$ref": "/schemas/foo-item" }
}

But, if you have schema without method,

{
  "rel": "collection",
  "href": "/foos",
  "schema": { "$ref": "/schemas/foo-item" }
}

there is no reason method should be interpreted as post. It could be interpreted as get which would make it a completely different link. Actually, I don't think it should be interpreted as anything and schema should be ignored.

handrews commented 7 years ago

@jdesrosiers:

This gets back to "method" being a confusing mess that needs removing. I should have included "method": "post" in all of my links in order to be unambiguously compliant with Draft 06 (I'll explain why that works in a bit). In Draft 06, the only thing that "method" does is determine whether "encType" and "schema" apply to the URL query string (as named params) or to the request body.

In Draft 06, the form-encoded URL query string and any and all other portions of the URI are more flexibly and comprehensively specified by "hrefSchema", which defines a schema for the URI Template variables. A template of "/foos{?offset,limit}" with an "hrefSchema" defining "offset" and "limit" properties in Draft 06 behaves identically to a "schema" defining "offset" and "limit" with a "method" of "get" in Draft 04.

Crucially, "hrefSchema" and "schema" can be used at the same time. This allows both defining a schema for URI query parameters (and other URI Template variables) and defining a schema for a request body.

So in Draft 06, there is never any reason to use "method": "get" except for backwards compatibility. The only truly useful value of "method" in Draft 06 is "post", so I tend to forget and leave "method" out entirely. Because it's confusing. You don't need it (because only one possible value is useful) and the values do not mean what people think they mean.

I have argued and continue to argue that having a keyword called "method" that takes two values that appear to be HTTP methods but are actually not HTTP methods is a horrible confusing approach that needs to be removed ASAP, and I will take up that cause again in Draft 07. It is also a problem for documentation or static inspection that JSON Hyper-Schema does not offer a mechanism for hinting at HTTP method allowance (hinting because the resource can always return 405 Not Allowed, possibly transiently due to application state). I also plan to revisit that in Draft 07.

But the documentation/hinting of HTTP method usage and the specification of URL query parameters vs request bodies are completely orthogonal problems, no matter what the HTML history is. HTML forms were designed to abstract the submission mechanisms away from human users, and have never evolved beyond their original limitations due to the rise of JavaScript. Web apps that want to do something other than the behaviors allowed by HTML forms get around it with JavaScript. That doesn't make any sense for JSON Hyper-Schema. It should be fully functional on its own, without requiring workarounds through code-on-demand.

Anyway, a Draft 06 "method": "post" link can be used with any and all HTTP methods, assuming you are respecting proper HTTP semantics (supporting abuse of HTTP semantics is a real-world practical issue and we'll need to look at that, too, but let's punt that for the moment):

The request format for PATCH is determined by "targetSchema" plus the media type rules for the type(s) given in the "Accept-Patch" HTTP header. JSON Hyper-Schema doesn't provide a way to hint at or document "Accept-Patch", which is the same problem as the HTTP method hinting, which corresponds to the "Allow" HTTP header. We need to solve those problems, which is the right way to support PATCH (instead of overloading the use of "schema").


This is how linking works in most, if not all, hypermedia systems.

There are other JSON-based things that start describing methods, but they (and, I argue, Draft 04 of JSON Hyper-Schema) are confused about the difference between hypermedia (ensures that links can be recognized with enough protocol and link relation type information to allow a client to know how they could be used) and API specifications (describes the exact HTTP usage allowed for each instance of a link)

We need to figure out something about API specification functionality, because people want it. But it is not part of hypermedia, and we need to keep those concepts separate. This could be done through another JSON Schema vocabulary, or it could by done the way the validation and metadata keywords are handled in the JSON Schema Validation specification: each keyword is clearly designated to function as either a validation or a metadata keyword. No keyword conflates the two.

I think that ensuring that we separate those concerns, whether by vocabulary or just be documenting them as having different purposes, we will avoid a great deal of the confusion that is currently present. And perhaps that will also help us figure out a way to support APIs that abuse HTTP semantics without impacting either proper HTTP usage or documentation.

handrews commented 7 years ago

@jdesrosiers Also, I forgot "create" was in Draft 04 (it and "instances" were removed in Draft 05). "instances" is obviously redundant with "collection". "create"'s closest IANA-registered analogue "create-form", which is a better link name (relation, not action).

I think the "create-form" target resource needs to be the form rather than the resource to which the form is submitted, so that type of link would probably point to the collection's schema, because its "self" link's "schema" would be the form in question. I find just recognizing the "collection" link relation and applying the POST-to-create pattern more consistent, but I also see room for disagreement there.

jdesrosiers commented 7 years ago

It seems that we have different interpretations of how the schema keyword is supposed to be applied.

The way I see it, the schema keyword is a non-optional part of the link. You can't decide to ignore it because you are making a GET request and a GET isn't supposed to have a body. However, an HTTP client should recognize that it doesn't know how to construct a request for a link with a schema using anything other than POST and behave accordingly. (Our disagreement really had nothing to do with method, so I'll ignore that diatribe unless there is some part you specifically would like me to respond to. We are mostly on the same page.)


After some more thought about "create" vs "collection", I've decided that I very much prefer your pattern of using "collection". However, I can't get over the fact that it is undocumented behavior. It doesn't matter how intuitive or widely accepted the pattern is, we can't just assume a relation that was clearly and formally defined also has this other behavior. It would be nice if "collection" defined this behavior, but since it doesn't, the options are to create a new pair of "collection" / "item" -like relations, or use the existing relations and augment their behavior with something like "create".

I don't think that "create-form", as defined, can really fill the role that "create" played. A resource that is related by "create-form" is supposed to be a resource that contains a form. That doesn't really help. If we have a creation link on the foo-collection schema, we could have a "create-form" link on the foo-item schema that points to the collection. That IMHO is a proper use of "create-form". That doesn't mean I don't like your interpretation. I like the idea, I just think it differs from the intended semantics of "create-form". Of course we could always create a new relation with those semantics if we wanted. Maybe something like "create-schema".

handrews commented 7 years ago

@jdesrosiers

The way I see it, the schema keyword is a non-optional part of the link. You can't decide to ignore it because you are making a GET request and a GET isn't supposed to have a body.

Could you cite some motivation for this view in Draft 06? The JSON Schema specification is our specification. It means what we way it means. If there is something in Draft 06 that implies that "schema" must be used in this manner, that is a bug and we can fix it. It has been discussed multiple times in the process of writing Drafts 05 and 06 that a single LDO is intended for use with multiple HTTP methods, so the intent is clear to me. We just need to make sure that the intent is clear to the average reader of the spec.

However, I cannot find any such statements looking over Draft 06 right now. "targetSchema" explicitly states that it has different uses with HTTP GET vs PUT (capitalized so that they are clearly distinct from the explicitly lowercase "get" and "post" values of "method"). "schema" just doesn't say anything one way or the other. It is documented in the form of "if there is user input and method is X then user input is handled in way Y", which is not the same thing as "the presence of this keyword forces there to be user input." If you read it differently, please indicate exactly which parts imply required behavior so we can change them.

After some more thought about "create" vs "collection", I've decided that I very much prefer your pattern of using "collection". However, I can't get over the fact that it is undocumented behavior. It doesn't matter how intuitive or widely accepted the pattern is, we can't just assume a relation that was clearly and formally defined also has this other behavior.

This is exactly why I say that I see room for disagreement here. But this also comes up over and over with IANA-registered link relations. They are intentionally broadly defined, and will continue to be intentionally broadly defined. I don't know what the solution is (other than making up more "create"-ish relation types). RFC 5988 explicitly forbids treating combinations of relation types differently from relation types that are present separately, so "collection" + "create" should not be treated differently from "create" or "collection" individually.

One option is to document the usage of underspecified link relation types in a given API, but it's not clear to me how that fits with generic clients. It's not truly generic if you have to read non-standardized documentation.

This exact ambiguity is where I am struggling most with how to approach hypermedia.

jdesrosiers commented 7 years ago

I responded to some of this in #276, so I won't repeat that here.

"targetSchema" explicitly states that it has different uses with HTTP GET vs PUT

And it has no behavior with DELETE. The fact that the behavior of targetSchema is coupled to the HTTP methods just reinforces my belief that targetSchema is broken (since draft-05) and should not exist (since always). There is some grounds for your interpretation of schema based on the way targetSchema is defined, but I think it would be building upon a wart in the specification and not the direction we should be going.

RFC 5988 explicitly forbids treating combinations of relation types differently from relation types that are present separately, so "collection" + "create" should not be treated differently from "create" or "collection" individually.

Good point. I don't think that would be an issue for "create", but it would for the "create-schema" concept.

One option is to document the usage of underspecified link relation types in a given API, but it's not clear to me how that fits with generic clients. It's not truly generic if you have to read non-standardized documentation.

Agreed. In fact I've found very few of the IANA registered relations to be usable outside of the specific context they were designed for. Even "edit", which seems like it should be fairly generic, references constructs defined in Atom and therefore isn't reusable outside of Atom. Clearly something more is needed. RDO is the best way I've been able to come up with to address this problem.

handrews commented 7 years ago

The fact that the behavior of targetSchema is coupled to the HTTP methods...

I don't think it is. "targetSchema" hints at the schema for the representation of the target resource. It is not a response schema. HTTP semantics require that all of the following be a representation of the target resource, and therefore (assuming the hint is correct) be valid against "targetSchema":

The semantics of PATCH define the request in terms of both the resource representation and the request media type, so there is an indirect relation between PATCH requests and "targetSchema"

Of course the representation of the target resource is irrelevant to a DELETE request, and with a POST request there is no guarantee of any relationship between the target resource representation and the request document. So "targetSchema" is irrelevant to those methods.

But all of this is defined by RFC 7231 (HTTP Semantics) and RFC 5789 (PATCH). It has nothing to do with JSON Hyper-Schema at all. "targetSchema" always means the same thing, but that thing applies differently to each HTTP method in a well-defined way.

RDO is the best way I've been able to come up with to address this problem.

I still find the RDO an interesting concept, I'm just not convinced that it belongs in the Hyper-Schema spec. I'm not 100% convinced it doesn't, either. Mostly I feel like I'm missing something about link relation types. Which is why I'm pestering mnot on mnot/I-D#211 :-)

handrews commented 7 years ago

@jdesrosiers I just read through RFC 6573: "The Item and Collection Link Relations " and noticed that it lists application/vnd.collection+json and application/vnd.maze+xml as two examples of usage. Both of those specifications define that a "collection" link means that HTTP POST can be used to create a collection item.

So I think once Draft 06 is out the door I'll file a new issue for JSON Hyper-Schema to reference RFC 6573 and specify the semantics of those link relations in the context of application/schema+json. That seems to be both valid an useful. And would be enough information for a generic client to process correctly. An HTTP header with a rel of "collection" is not guaranteed to accept a POST to create, but we can specify that an API claiming a conforming use of Hyper-Schema MUST either do so or return a 405 Not Allowed for POST. Or maybe SHOULD. We can debate it after Draft 06 is out.

The general issue of overly broad link relations is still an issue, but it seems like this case seems easy enough to solve. This would unambiguously replace Draft 04's proposed "instances" and "create" link relations with existing IANA-registered link relations.

Relequestual commented 7 years ago

After discussion elsewhere with @handrews and rereading this issue, the problem (for me at least) is the false assumption that I can use JSON Hyper Schema to document my non hypermedia compliant API.

I think what we need is a preface on how to determine if using JSON Hyper Schema is "right for my API", and how to identify (or define, I don't know) whay a hypermedia API looks like. Maybe explain a few different situations. It looks like draft-4 allowed the abuse of JSH to document non hypermeida APIs.

I'm still wrapping my head round what hypermeida IS and how it can be used. I'm planning to collate a list of articles and documentation on JSON Schema in general, but also about hypermeida APIs and JSON Hyper Schema.

Given I gave a talk about JSON Schema and how to use it for a hypermedia API last week, and I'm still a bit confused about stuff, I think this should be our main address for draft-7.

handrews commented 7 years ago

@Relequestual FWIW I think that we should also have keywords that are documentation-oriented. I don't think that static documentation and dynamic hypermedia are incompatible, they're just different things that need different support. For instance, #73 is a way to support static documentation, but it did not get momentum for Draft 06 (and see also mnot/I-D#211 for more discussion related to the topic of HTTP hints).

jdesrosiers commented 7 years ago

@Relequestual, I don't think it's right to think about Hyper-Schema as documentation. I often refer to Hypermedia APIs as self documenting, but it's more about reducing the number of things that need documenting. It's kinda like if you referred to the method signatures in your classes as documentation. In a way they are, but they are also parseable, executable, and an integral part of the system.

handrews commented 7 years ago

@Relequestual @jdesrosiers I'm part of the way through a big comparison of hypermedia vs API description which I'll put on the wiki. Or maybe our web site through the other repo. I just got distracted replying to #280 so it will have to wait until tomorrow :-)

Relequestual commented 7 years ago

Great thanks @handrews this will be super useful. I think as a first pass it should go on the wiki with a view to probably migrate it to the website once us non hypermedia understanding luddites feel the comparison and explaianition is sufficent to make sense =]

eviratec commented 7 years ago

@Relequestual you might find my schemas useful...I'm currently adding/updating them daily... https://github.com/eviratec/schema/tree/master/v1

Also see for examples of objects which are considered valid the schemas https://github.com/eviratec/schema/tree/master/docs/v1

Anthropic commented 7 years ago

@handrews will you post an update here when done? I've always felt I didn't really understand the point of the hypermedia spec correctly coming from a different starting perspective.