Skip to content

Resource Versioning Profile #1333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 27 commits into
base: gh-pages
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
df9838a
Create resource-versioning index.md.
gabesullice Dec 12, 2018
e815ccd
Add a "Resource Versioning" profile category
gabesullice Dec 13, 2018
c302a8c
Add all editors to this profile
gabesullice Dec 13, 2018
84d4840
Fix spacing
gabesullice Dec 13, 2018
ea9c13c
Use editor format from #1349
gabesullice Dec 20, 2018
9d9e263
move 501 to relative version section
gabesullice Dec 20, 2018
9368cbc
disambiguate bad version negotiator vs. argument errors
gabesullice Dec 20, 2018
d3c1d13
add trailing slash to error type URIs
gabesullice Dec 20, 2018
cac4baf
add linking and version history section
gabesullice Dec 20, 2018
56bc05e
fixup link and version history commit
gabesullice Dec 20, 2018
75659ce
add to and fix link example table
gabesullice Dec 20, 2018
2d5346e
typos and clarification
gabesullice Dec 20, 2018
c351d9c
change the query parameter from snake-case to camel-case
gabesullice Dec 20, 2018
3e4b67e
clarify that a one-segment version identifier is valid
gabesullice Dec 21, 2018
515aba9
invert definition of a version
gabesullice Dec 21, 2018
0feddd6
clarify the example narrative of a version history
gabesullice Dec 21, 2018
b0a1e3d
relax `type` link requirement
gabesullice Dec 21, 2018
f0d73db
clarify interoperability and optionality of version negotiators
gabesullice Dec 21, 2018
a4329d5
the first or only segment of a version identifier must be interpreted…
gabesullice Dec 21, 2018
7a352dc
restrict usage of the rel negotiator in resource objects' `self` links
gabesullice Dec 21, 2018
9129eb2
reduce redundancy
gabesullice Dec 21, 2018
ba9bf0b
use the `source` error object member in error details
gabesullice Dec 21, 2018
6bc95be
disallow custom rel-based version arguments
gabesullice Dec 21, 2018
1a1395d
reorder two lines
gabesullice Dec 21, 2018
e4adbd7
fix some ascii art
gabesullice Dec 21, 2018
5c5b0f4
fix italicization
gabesullice Dec 21, 2018
c82ecbe
update mateu's contact info
gabesullice Dec 21, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ quicklinks:

profile_categories:
- Pagination
- Resource Versioning
# these are some other potential categories.
# Uncomment them if you're adding a profile in one of these categories.
# - Filtering
Expand Down
179 changes: 179 additions & 0 deletions _profiles/drupal/resource-versioning/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
---
name: Resource Versioning
short_description: |
Defines a protocol for requesting versioned resources via a JSON:API
server.

extended_description: |
# Overview
JSON:API servers that are capable of tracking a record of changes to a
resource object may afford the capability of requesting a resource object
as it existed in a prior or successive state. This capability is herein
defined as _resource versioning_.

This profile establishes a protocol for resource versioning by defining a
query parameter and its semantics in order to identify arbitrary revisions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revisions → versions :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in this instance, remember: "not all revisions are versions, but all versions are revisions"

of a resource and how a server should interpret this query parameter.

minimum_jsonapi_version: 1.0
minimum_jsonapi_version_explanation:

discussion_url: https://www.drupal.org/project/issues/jsonapi

editors:
- name: Gabriel Sullice
email: gabriel@sullice.com
- name: Mateu Aguiló Bosch
email: mateu.aguilo.bosch@gmail.com
website: https://humanbits.es
- name: Wim Leers
email: work@wimleers.com
website: https://wimleers.com

categories:
- Resource Versioning
---

# Concepts
Resources on a server may undergo changes and the state of a resource with an
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that by "the state […] may be accessible", you mean that each state may be individually accessible?

arbitrary number of changes may be accessible. It is often useful to retrieve
resources as they existed at the time of their creation or in various states of
change for editorial or archival purposes. This profile establishes a protocol
for accessing resources in those various states.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is talking about previous states, for archival/history purposes. I think this should also explicitly state next states, i.e. drafts that are actively being worked on, or perhaps need to go through legal review, or are ready but simply aren't yet live because they're scheduled to be published in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is talking about previous states, for archival/history purposes.

I agree that this could be clarified, but I did not mean previous as you are interpreting it.

Even future revisions were created previously to now. They may not be the default version yet, but that does not mean that the revision itself was created in the future.


For the purpose of understanding this profile, it is helpful to establish a
vocabulary for describing various possible states of a resource.

A _revision_ is to be understood as an identifiable state of a resource after
its creation or after some number of changes.

A _version_ is to be understood as a revision of a resource that is available,
or was previously available, without any version negotiation. In other words, as
a revision that is or was the default revision of a resource.

A _working copy_ is the revision to which new changes can be made or to which
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This term is specifically borrowed from
https://tools.ietf.org/html/rfc5829, because this entire profile was modeled after RFC5829. Linking to that at the top of the "Concepts" section would be helpful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, I can't believe that I didn't already do that.

they will be applied. Colloquially, a working copy is often thought of as the
"tip" of a version history.

For example, a resource which existed as a draft and underwent multiple changes
before the resource was published may have many revisions. Only the published
revision would be considered a version. The revisions prior to first version
would have been known as the working copy as each one was created.

If the version is then checked out for further changes (which may or may not be
published) each new revision becomes the working copy.

Sophisticated servers may support multiple versions of a resource as well as
multiple working copies of a resource (e.g., to support multiple
languages or within a version control system which supports multiple branches).

This profile creates a standard for JSON:API to support these diverse versioning
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"these diverse" refers to both the "multiple versions" and "multiple working copies" in the preceding paragraph. Therefore I think it should be "diverse revisioning schemes", not "diverse versioning schemes"? (Because "versioning" refers only to versions, not to working copies.)

schemes.
# Query Parameter

## Usage

An endpoint **MAY** support a `resource_version` query parameter to allow a
client to indicate which version(s) of a resource should be returned.

If an endpoint does not support the `resource_version` parameter, it **MUST**
respond with `400 Bad Request` to any requests that include it.

If an endpoint supports the `resource_version` parameter and a client supplies
it:

- The server’s response **MUST** contain the most appropriate version of the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "the most appropriate" is unnecessarily vague. Can't we change the most appropiate version to the requested version?

resource requested.
- The server **MUST NOT** include a version of a resource inappropriate for the
requested version.
- The server **MUST** respond with `404 Not Found` if an appropriate version of
the resource requested cannot be located.

> Note: This means that a server should not provide "fallbacks" unless the
> behavior is well defined by the version negotiation mechanism (see below).
> These rules apply to individual and collection endpoints alike.

## Format

The value of the `resource_version` parameter **MUST** be a colon-separated
(U+003A COLON, “:”) string. The first segment of the string **SHOULD** be
interpreted as an identifier for a _version negotiation mechanism_. A version
negotiation mechanism defines how a server will locate an appropriate resource
version. Subsequent segments of the string **SHOULD** be interpreted as version
negotiation arguments for the preceding mechanism. Collectively, this query
parameter value is known as the _version identifier_.

> Note: For example, a server may support both ID-based and time-based
> mechanisms for requesting a resource version. The former mechanism would be
> useful for comparing versions and the latter could be useful for requesting a
> resource as it existed at an arbitrary point in time. This profile does not
> attempt to define every possible mechanism for versioning resources.

```
version-identifier
_______|_________
/ \
?resource_version=rel:latest-version
\_/ \____________/
| |
version-negotiator |
version-argument
```

## Server Responsibilities

<a id="bad-version-negotiator"></a>A server **MUST** respond with `400 Bad Request` if a version negotiator is not
supported. In this case, an error object that includes a `type` link to
`https://jsonapi.org/profiles/drupal/resource-versioning/#bad-version-negotiator`
**MUST** be included in the response document.

<a id="bad-version-argument"></a>If a server cannot process the given version argument for the given negotiation
mechanism, it **MUST** respond with a `400 Bad Request`. In this case, an error
object that includes a `type` link to
`https://jsonapi.org/profiles/drupal/resource-versioning/#bad-version-argument`
**MUST** be included in the response document.

If a server is able to process the version argument but an appropriate version
cannot be located, the server **MUST** respond with a `404 Not Found`.

# Version Negotiators
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Design feedback/interoperable implementations review requirement] If I'm understanding correctly, each server implementation can define its own version negotiators, with multiple servers using the same negotiator name in different ways (and no central registry). That seems not great for interoperability. It would also seem to mean that no other version negotiators can ever be standardized as part of this profile, because they could conflict with existing implementations. Is that really what you want?

My gut instinct would be to make this profile's spec the canonical list of all legal version negotiators. Then, you can add more over time to this spec as they're requested. To support people who really need to use a version negotiator that isn't part of your profile, you could have some set of negotiator names/schemes/namespaces that are allowed to have implementation-specific meanings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I've done is applied the implementation-specific query parameter name constraints as a version negotiator constraint and added a mechanism for adding new negotiators to the profile.

Changes here: f0d73db

Elsewhere, @e0ipso suggest that we use URIs but I think this is sufficient. @e0ipso, WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc: @wimleers cause it's his inbox that I suggested too 😛

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with that. However I still think that doc curies offer a lower barrier of entry. One could document the new crazy negotiator in their blog and have the server implementation point to that, instead of adding it here.

Many will just not go through the trouble to send their idea to some email addresses and be potentially blocked by them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I wanted to discourage non-standard negotiators being used as a standard and keep them isolated. My feeling was that sending an email saying "hey, I'd like to add a negotiator like this..." doesn't seem like a super high barrier. In some ways, it's even less difficult than opening a PR.

What if we add this:

Note: Don't be shy! New version negotiators are more than welcome, the editors want to see this profile proliferate and that means accepting versioning strategies like yours!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@e0ipso, would that work?


## ID-Based Version Negotiator

This profile establishes the `id` version negotiator. An `id`-based version
identifier is composed of two segments—the `id` version negotiator and a single
version argument. Any colons (U+003A COLON, “:”) present in the version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should say that the version argument is an opaque string.

identifier after the first occurrence **MUST** be interpreted as part of the
single version argument and **MUST NOT** be interpreted as a segment delimiter.

The resource version returned for any given version argument in an `id`-based
version identifier **MUST NOT** change over time.

> Note: This profile is agnostic about the format of the version argument in
> `id`-based version identifiers. For example, one server may use integers as
> revision IDs, another may use UUIDs and yet another may use content-based
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note could go away by defining it as an opaque string, like I suggested above.

> hashes.

## Relative Version Negotiator

This profile establishes the `rel` version negotiator. A `rel`-based version
identifier is composed of two or more segments. The first segment **MUST** be
`rel` and the following version arguments describe a resource version that is
relative to the version history.

The resource version returned for any given version argument in a `rel`-based
version identifier **MAY** change over time.

The `rel` version negotiator has the following valid version argument strings:

- `latest-version`: requests the latest default revision of a resource.
- `working-copy`: requests revision of a resource to which changes can be
made.

If any of the following version arguments is received in a `rel`-based version
identifier, the server **MUST** respond with a `501 Not Implemented`:

- `predecessor-version`
- `successor-version`
- `prior-working-copy`
- `subsequent-working-copy`
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy