Rust implementation of OCI Distribution Spec with granular access control
1# Open Container Initiative Distribution Specification
2
3## Table of Contents
4
5- [Overview](#overview)
6 - [Introduction](#introduction)
7 - [Historical Context](#historical-context)
8 - [Definitions](#definitions)
9- [Notational Conventions](#notational-conventions)
10- [Use Cases](#use-cases)
11- [Conformance](#conformance)
12 - [Official Certification](#official-certification)
13 - [Requirements](#requirements)
14 - [Workflow Categories](#workflow-categories)
15 1. [Pull](#pull)
16 2. [Push](#push)
17 3. [Content Discovery](#content-discovery)
18 4. [Content Management](#content-management)
19- [Backwards Compatibility](#backwards-compatibility)
20 - [Unavailable Referrers API](#unavailable-referrers-api)
21- [Upgrade Procedures](#upgrade-procedures)
22 - [Enabling the Referrers API](#enabling-the-referrers-api)
23- [API](#api)
24 - [Endpoints](#endpoints)
25 - [Error Codes](#error-codes)
26 - [Warnings](#warnings)
27- [Appendix](#appendix)
28
29
30## Overview
31
32### Introduction
33
34The **Open Container Initiative Distribution Specification** (a.k.a. "OCI Distribution Spec") defines an API protocol to facilitate and standardize the distribution of content.
35
36The specification is designed to be agnostic of content types.
37OCI Image types are currently the most prominent, which are defined in the [Open Container Initiative Image Format Specification](https://github.com/opencontainers/image-spec) (a.k.a. "OCI Image Spec").
38
39### Historical Context
40
41The spec is based on the specification for the Docker Registry HTTP API V2 protocol <sup>[apdx-1](#appendix)</sup>.
42
43For relevant details and a history leading up to this specification, please see the following issues:
44
45- [moby/moby#8093](https://github.com/moby/moby/issues/8093)
46- [moby/moby#9015](https://github.com/moby/moby/issues/9015)
47- [docker/docker-registry#612](https://github.com/docker/docker-registry/issues/612)
48
49#### Legacy Docker support HTTP headers
50
51Because of the origins of this specification, the client MAY encounter Docker-specific headers, such as `Docker-Content-Digest`, or `Docker-Distribution-API-Version`.
52These headers are OPTIONAL and clients SHOULD NOT depend on them.
53
54#### Legacy Docker support error codes
55
56The client MAY encounter error codes targeting Docker schema1 manifests, such as `TAG_INVALID`, or `MANIFEST_UNVERIFIED`.
57These error codes are OPTIONAL and clients SHOULD NOT depend on them.
58
59### Definitions
60
61Several terms are used frequently in this document and warrant basic definitions:
62
63- **Registry**: a service that handles the required APIs defined in this specification
64- **Repository**: a scope for API calls on a registry for a collection of content (including manifests, blobs, and tags).
65- **Client**: a tool that communicates with Registries
66- **Push**: the act of uploading blobs and manifests to a registry
67- **Pull**: the act of downloading blobs and manifests from a registry
68- **Blob**: the binary form of content that is stored by a registry, addressable by a digest
69- **Manifest**: a JSON document uploaded via the manifests endpoint. A manifest may reference other manifests and blobs in a repository via descriptors. Examples of manifests are defined under the OCI Image Spec <sup>[apdx-2](#appendix)</sup>, such as the image manifest and image index (and legacy manifests).</sup>
70- **Image Index**: a manifest containing a list of manifests, defined under the OCI Image Spec <sup>[apdx-6](#appendix)</sup>.
71- **Image Manifest**: a manifest containing a config descriptor and an indexed list of layers, commonly used for container images, defined under the OCI Image Spec <sup>[apdx-2](#appendix)</sup>.
72- **Config**: a blob referenced in the image manifest which contains metadata. Config is defined under the OCI Image Spec <sup>[apdx-4](#appendix)</sup>.
73- **Object**: one conceptual piece of content stored as blobs with an accompanying manifest. (This was previously described as an "artifact")
74- **Descriptor**: a reference that describes the type, metadata and content address of referenced content. Descriptors are defined under the OCI Image Spec <sup>[apdx-5](#appendix)</sup>.
75- **Digest**: a unique identifier created from a cryptographic hash of a Blob's content. Digests are defined under the OCI Image Spec <sup>[apdx-3](#appendix)</sup>
76- **Tag**: a custom, human-readable pointer to a manifest. A manifest digest may have zero, one, or many tags referencing it.
77- **Subject**: an association from one manifest to another, typically used to attach an artifact to an image.
78- **Referrers List**: a list of manifests with a subject relationship to a specified digest. The referrers list is generated with a [query to a registry](#listing-referrers).
79
80## Notational Conventions
81
82The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119) (Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997).
83
84## Use Cases
85
86### Content Verification
87
88A container engine would like to run verified image named "library/ubuntu", with the tag "latest".
89The engine contacts the registry, requesting the manifest for "library/ubuntu:latest".
90An untrusted registry returns a manifest.
91After each layer is downloaded, the engine verifies the digest of the layer, ensuring that the content matches that specified by the manifest.
92
93### Resumable Push
94
95Company X's build servers lose connectivity to a distribution endpoint before completing a blob transfer.
96After connectivity returns, the build server attempts to re-upload the blob.
97The registry notifies the build server that the upload has already been partially attempted.
98The build server responds by only sending the remaining data to complete the blob transfer.
99
100### Resumable Pull
101
102Company X is having more connectivity problems but this time in their deployment datacenter.
103When downloading a blob, the connection is interrupted before completion.
104The client keeps the partial data and uses http `Range` requests to avoid downloading repeated data.
105
106### Layer Upload De-duplication
107
108Company Y's build system creates two identical layers from build processes A and B.
109Build process A completes uploading the layer before B.
110When process B attempts to upload the layer, the registry indicates that its not necessary because the layer is already known.
111
112If process A and B upload the same layer at the same time, both operations will proceed and the first to complete will be stored in the registry.
113Even in the case where both uploads are accepted, the registry may securely only store one copy of the layer since the computed digests match.
114
115## Conformance
116
117For more information on testing for conformance, please see the [conformance README](./conformance/README.md)
118
119### Official Certification
120
121Registry providers can self-certify by submitting conformance results to [opencontainers/oci-conformance](https://github.com/opencontainers/oci-conformance).
122
123### Requirements
124
125Registry conformance applies to the following workflow categories:
126
1271. **Pull** - Clients are able to pull from the registry
1282. **Push** - Clients are able to push to the registry
1293. **Content Discovery** - Clients are able to list or otherwise query the content stored in the registry
1304. **Content Management** - Clients are able to control the full life-cycle of the content stored in the registry
131
132All registries conforming to this specification MUST support, at a minimum, all APIs in the **Pull** category.
133
134Registries SHOULD also support the **Push**, **Content Discovery**, and **Content Management** categories.
135A registry claiming conformance with one of these specification categories MUST implement all APIs in the claimed category.
136
137In order to test a registry's conformance against these workflow categories, please use the [conformance testing tool](./conformance/).
138
139### Workflow Categories
140
141#### Pull
142
143The process of pulling an object centers around retrieving two components: the manifest and one or more blobs.
144
145Typically, the first step in pulling an object is to retrieve the manifest. However, you MAY retrieve content from the registry in any order.
146
147##### Pulling manifests
148
149To pull a manifest, perform a `GET` request to a URL in the following form:
150`/v2/<name>/manifests/<reference>` <sup>[end-3](#endpoints)</sup>
151
152`<name>` refers to the namespace of the repository.
153`<reference>` MUST be either (a) the digest of the manifest or (b) a tag.
154The `<reference>` MUST NOT be in any other format.
155Throughout this document, `<name>` MUST match the following regular expression:
156
157`[a-z0-9]+((\.|_|__|-+)[a-z0-9]+)*(\/[a-z0-9]+((\.|_|__|-+)[a-z0-9]+)*)*`
158
159_Implementers note:_
160Many clients impose a limit of 255 characters on the length of the concatenation of the registry hostname (and optional port), `/`, and `<name>` value.
161If the registry name is `registry.example.org:5000`, those clients would be limited to a `<name>` of 229 characters (255 minus 25 for the registry hostname and port and minus 1 for a `/` separator).
162For compatibility with those clients, registries should avoid values of `<name>` that would cause this limit to be exceeded.
163
164Throughout this document, `<reference>` as a tag MUST be at most 128 characters in length and MUST match the following regular expression:
165
166`[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}`
167
168The client SHOULD include an `Accept` header indicating which manifest content types it supports.
169In a successful response, the `Content-Type` header will indicate the type of the returned manifest.
170The registry SHOULD NOT include parameters on the `Content-Type` header.
171The client SHOULD ignore parameters on the `Content-Type` header.
172The `Content-Type` header SHOULD match what the client [pushed as the manifest's `Content-Type`](#pushing-manifests).
173If the manifest has a `mediaType` field, clients SHOULD reject unless the `mediaType` field's value matches the type specified by the `Content-Type` header.
174For more information on the use of `Accept` headers and content negotiation, please see [Content Negotiation](./content-negotiation.md) and [RFC7231](https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1).
175
176A GET request to an existing manifest URL MUST provide the expected manifest, with a response code that MUST be `200 OK`.
177A successful response SHOULD contain the digest of the uploaded blob in the header `Docker-Content-Digest`.
178
179The `Docker-Content-Digest` header, if present on the response, returns the canonical digest of the uploaded blob which MAY differ from the provided digest.
180If the digest does differ, it MAY be the case that the hashing algorithms used do not match.
181See [Content Digests](https://github.com/opencontainers/image-spec/blob/v1.0.1/descriptor.md#digests) <sup>[apdx-3](#appendix)</sup> for information on how to detect the hashing algorithm in use.
182Most clients MAY ignore the value, but if it is used, the client MUST verify the value matches the returned manifest.
183If the `<reference>` part of a manifest request is a digest, clients SHOULD verify the returned manifest matches this digest.
184
185If the manifest is not found in the repository, the response code MUST be `404 Not Found`.
186
187##### Pulling blobs
188
189To pull a blob, perform a `GET` request to a URL in the following form:
190`/v2/<name>/blobs/<digest>` <sup>[end-2](#endpoints)</sup>
191
192`<name>` is the namespace of the repository, and `<digest>` is the blob's digest.
193
194A GET request to an existing blob URL MUST provide the expected blob, with a response code that MUST be `200 OK`.
195A successful response SHOULD contain the digest of the uploaded blob in the header `Docker-Content-Digest`.
196If present, the value of this header MUST be a digest matching that of the response body.
197Most clients MAY ignore the value, but if it is used, the client MUST verify the value matches the returned response body.
198Clients SHOULD verify that the response body matches the requested digest.
199
200If the blob is not found in the repository, the response code MUST be `404 Not Found`.
201
202A registry SHOULD support the `Range` request header in accordance with [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-range-requests).
203
204##### Checking if content exists in the registry
205
206In order to verify that a repository contains a given manifest or blob, make a `HEAD` request to a URL in the following form:
207
208`/v2/<name>/manifests/<reference>` <sup>[end-3](#endpoints)</sup> (for manifests), or
209
210`/v2/<name>/blobs/<digest>` <sup>[end-2](#endpoints)</sup> (for blobs).
211
212A HEAD request to an existing blob or manifest URL MUST return `200 OK`.
213A successful response SHOULD contain the digest of the uploaded blob in the header `Docker-Content-Digest`.
214A successful response SHOULD contain the size in bytes of the uploaded blob in the header `Content-Length`.
215
216If the blob or manifest is not found in the repository, the response code MUST be `404 Not Found`.
217
218#### Push
219
220Pushing an object typically works in the opposite order as a pull: the blobs making up the object are uploaded first, and the manifest last.
221A useful diagram is provided [here](https://github.com/google/go-containerregistry/tree/d7f8d06c87ed209507dd5f2d723267fe35b38a9f/pkg/v1/remote#anatomy-of-an-image-upload).
222
223A registry MUST initially accept an otherwise valid manifest with a `subject` field that references a manifest that does not exist in the repository, allowing clients to push a manifest and referrers to that manifest in either order.
224A registry MAY reject a manifest uploaded to the manifest endpoint with descriptors in other fields that reference a manifest or blob that does not exist in the registry.
225When a manifest is rejected for this reason, it MUST result in one or more `MANIFEST_BLOB_UNKNOWN` errors <sup>[code-1](#error-codes)</sup>.
226
227##### Pushing blobs
228
229There are two ways to push blobs: chunked or monolithic.
230
231##### Pushing a blob monolithically
232
233There are two ways to push a blob monolithically:
2341. A `POST` request followed by a `PUT` request
2352. A single `POST` request
236
237---
238
239###### POST then PUT
240
241To push a blob monolithically by using a POST request followed by a PUT request, there are two steps:
2421. Obtain a session id (upload URL)
2432. Upload the blob to said URL
244
245To obtain a session ID, perform a `POST` request to a URL in the following format:
246
247`/v2/<name>/blobs/uploads/` <sup>[end-4a](#endpoints)</sup>
248
249Here, `<name>` refers to the namespace of the repository.
250Upon success, the response MUST have a code of `202 Accepted`, and MUST include the following header:
251
252```
253Location: <location>
254```
255
256The `<location>` MUST contain a UUID representing a unique session ID for the upload to follow.
257The `<location>` does not necessarily need to be provided by the registry itself.
258In fact, offloading to another server can be a [better strategy](https://www.backblaze.com/blog/design-thinking-b2-apis-the-hidden-costs-of-s3-compatibility/).
259
260Optionally, the location MAY be absolute (containing the protocol and/or hostname), or it MAY be relative (containing just the URL path).
261For more information, see [RFC 7231](https://tools.ietf.org/html/rfc7231#section-7.1.2).
262
263Once the `<location>` has been obtained, perform the upload proper by making a `PUT` request to the following URL path, and with the following headers and body:
264
265`<location>?digest=<digest>` <sup>[end-6](#endpoints)</sup>
266```
267Content-Length: <length>
268Content-Type: application/octet-stream
269```
270```
271<upload byte stream>
272```
273
274The `<location>` MAY contain critical query parameters.
275Additionally, it SHOULD match exactly the `<location>` obtained from the `POST` request.
276It SHOULD NOT be assembled manually by clients except where absolute/relative conversion is necessary.
277
278Here, `<digest>` is the digest of the blob being uploaded, and `<length>` is its size in bytes.
279
280Upon successful completion of the request, the response MUST have code `201 Created` and MUST have the following header:
281
282```
283Location: <blob-location>
284```
285
286With `<blob-location>` being a pullable blob URL.
287
288---
289
290###### Single POST
291
292Registries MAY support pushing blobs using a single POST request.
293
294To push a blob monolithically by using a single POST request, perform a `POST` request to a URL in the following form, and with the following headers and body:
295
296`/v2/<name>/blobs/uploads/?digest=<digest>` <sup>[end-4b](#endpoints)</sup>
297```
298Content-Length: <length>
299Content-Type: application/octet-stream
300```
301```
302<upload byte stream>
303```
304
305Here, `<name>` is the repository's namespace, `<digest>` is the blob's digest, and `<length>` is the size (in bytes) of the blob.
306
307The `Content-Length` header MUST match the blob's actual content length.
308Likewise, the `<digest>` MUST match the blob's digest.
309
310Registries that do not support single request monolithic uploads SHOULD return a `202 Accepted` status code and `Location` header and clients SHOULD proceed with a subsequent PUT request, as described by the [POST then PUT upload method](#post-then-put).
311
312Successful completion of the request MUST return a `201 Created` and MUST include the following header:
313
314```
315Location: <blob-location>
316```
317
318Here, `<blob-location>` is a pullable blob URL.
319This location does not necessarily have to be served by your registry, for example, in the case of a signed URL from some cloud storage provider that your registry generates.
320
321
322##### Pushing a blob in chunks
323
324A chunked blob upload is accomplished in three phases:
3251. Obtain a session ID (upload URL) (`POST`)
3262. Upload the chunks (`PATCH`)
3273. Close the session (`PUT`)
328
329For information on obtaining a session ID, reference the above section on pushing a blob monolithically via the `POST`/`PUT` method.
330The process remains unchanged for chunked upload, except that the post request MUST include the following header:
331
332```
333Content-Length: 0
334```
335
336If the registry has a minimum chunk size, the `POST` response SHOULD include the following header, where `<size>` is the size in bytes (see the blob `PATCH` definition for usage):
337
338```
339OCI-Chunk-Min-Length: <size>
340```
341
342Please reference the above section for restrictions on the `<location>`.
343
344---
345To upload a chunk, issue a `PATCH` request to a URL path in the following format, and with the following headers and body:
346
347URL path: `<location>` <sup>[end-5](#endpoints)</sup>
348```
349Content-Type: application/octet-stream
350Content-Range: <range>
351Content-Length: <length>
352```
353```
354<upload byte stream of chunk>
355```
356
357The `<location>` refers to the URL obtained from the preceding `POST` request.
358
359The `<range>` refers to the byte range of the chunk, and MUST be inclusive on both ends.
360The first chunk's range MUST begin with `0`.
361It MUST match the following regular expression:
362
363```regexp
364^[0-9]+-[0-9]+$
365```
366
367The `<length>` is the content-length, in bytes, of the current chunk.
368If the registry provides an `OCI-Chunk-Min-Length` header in the `POST` response, the size of each chunk, except for the final chunk, SHOULD be greater or equal to that value.
369The final chunk MAY have any length.
370
371Each successful chunk upload MUST have a `202 Accepted` response code, and MUST have the following headers:
372
373```
374Location: <location>
375Range: 0-<end-of-range>
376```
377
378Each consecutive chunk upload SHOULD use the `<location>` provided in the response to the previous chunk upload.
379
380The `<end-of-range>` value is the position of the last uploaded byte.
381
382Chunks MUST be uploaded in order, with the first byte of a chunk being the last chunk's `<end-of-range>` plus one.
383If a chunk is uploaded out of order, the registry MUST respond with a `416 Requested Range Not Satisfiable` code.
384A GET request may be used to retrieve the current valid offset and upload location.
385
386The final chunk MAY be uploaded using a `PATCH` request or it MAY be uploaded in the closing `PUT` request.
387Regardless of how the final chunk is uploaded, the session MUST be closed with a `PUT` request.
388
389---
390
391To close the session, issue a `PUT` request to a url in the following format, and with the following headers (and optional body, depending on whether or not the final chunk was uploaded already via a `PATCH` request):
392
393`<location>?digest=<digest>`
394```
395Content-Length: <length of chunk, if present>
396Content-Range: <range of chunk, if present>
397Content-Type: application/octet-stream <if chunk provided>
398```
399```
400OPTIONAL: <final chunk byte stream>
401```
402
403The closing `PUT` request MUST include the `<digest>` of the whole blob (not the final chunk) as a query parameter.
404
405The response to a successful closing of the session MUST be `201 Created`, and MUST contain the following header:
406```
407Location: <blob-location>
408```
409
410Here, `<blob-location>` is a pullable blob URL.
411
412---
413
414To get the current status after a 416 error, issue a `GET` request to a URL `<location>` <sup>[end-13](#endpoints)</sup>.
415
416The `<location>` refers to the URL obtained from any preceding `POST` or `PATCH` request.
417
418The response to an active upload `<location>` MUST be a `204 No Content` response code, and MUST have the following headers:
419
420```
421Location: <location>
422Range: 0-<end-of-range>
423```
424
425The following chunk upload SHOULD use the `<location>` provided in the response.
426
427The `<end-of-range>` value is the position of the last uploaded byte.
428
429##### Mounting a blob from another repository
430
431If a necessary blob exists already in another repository within the same registry, it can be mounted into a different repository via a `POST`
432request in the following format:
433
434`/v2/<name>/blobs/uploads/?mount=<digest>&from=<other_name>` <sup>[end-11](#endpoints)</sup>.
435
436In this case, `<name>` is the namespace to which the blob will be mounted.
437`<digest>` is the digest of the blob to mount, and `<other_name>` is the namespace from which the blob should be mounted.
438This step is usually taken in place of the previously-described `POST` request to `/v2/<name>/blobs/uploads/` <sup>[end-4a](#endpoints)</sup> (which is used to initiate an upload session).
439
440The response to a successful mount MUST be `201 Created`, and MUST contain the following header:
441```
442Location: <blob-location>
443```
444
445The Location header will contain the registry URL to access the accepted layer file.
446The Docker-Content-Digest header returns the canonical digest of the uploaded blob which MAY differ from the provided digest.
447Most clients MAY ignore the value but if it is used, the client SHOULD verify the value against the uploaded blob data.
448
449The registry MAY treat the `from` parameter as optional, and it MAY cross-mount the blob if it can be found.
450
451Alternatively, if a registry does not support cross-repository mounting or is unable to mount the requested blob, it SHOULD return a `202`.
452This indicates that the upload session has begun and that the client MAY proceed with the upload.
453
454##### Pushing Manifests
455
456To push a manifest, perform a `PUT` request to a path in the following format, and with the following headers and body: `/v2/<name>/manifests/<reference>` <sup>[end-7](#endpoints)</sup>
457
458Clients SHOULD set the `Content-Type` header to the type of the manifest being pushed.
459The client SHOULD NOT include parameters on the `Content-Type` header (see [RFC7231](https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1.1)).
460The registry SHOULD ignore parameters on the `Content-Type` header.
461All manifests SHOULD include a `mediaType` field declaring the type of the manifest being pushed.
462If a manifest includes a `mediaType` field, clients MUST set the `Content-Type` header to the value specified by the `mediaType` field.
463
464```
465Content-Type: application/vnd.oci.image.manifest.v1+json
466```
467Manifest byte stream:
468```
469{
470 "mediaType": "application/vnd.oci.image.manifest.v1+json",
471 ...
472}
473```
474
475`<name>` is the namespace of the repository, and the `<reference>` MUST be either a) a digest or b) a tag.
476
477The uploaded manifest MUST reference any blobs that make up the object.
478However, the list of blobs MAY be empty.
479
480The registry MUST store the manifest in the exact byte representation provided by the client.
481Upon a successful upload, the registry MUST return response code `201 Created`, and MUST have the following header:
482
483```
484Location: <location>
485```
486
487The `<location>` is a pullable manifest URL.
488The Docker-Content-Digest header returns the canonical digest of the uploaded blob, and MUST be equal to the client provided digest.
489Clients MAY ignore the value but if it is used, the client SHOULD verify the value against the uploaded blob data.
490
491An attempt to pull a nonexistent repository MUST return response code `404 Not Found`.
492
493A registry SHOULD enforce some limit on the maximum manifest size that it can accept.
494A registry that enforces this limit SHOULD respond to a request to push a manifest over this limit with a response code `413 Payload Too Large`.
495Client and registry implementations SHOULD expect to be able to support manifest pushes of at least 4 megabytes.
496
497###### Pushing Manifests with Subject
498
499When processing a request for an image manifest with the `subject` field, a registry implementation that supports the [referrers API](#listing-referrers) MUST respond with the response header `OCI-Subject: <subject digest>` to indicate to the client that the registry processed the request's `subject`.
500
501When pushing a manifest with the `subject` field and the `OCI-Subject` header was not set, the client MUST:
502
5031. Pull the current referrers list using the [referrers tag schema](#referrers-tag-schema).
5041. If that pull returns a manifest other than the expected image index, the client SHOULD report a failure and skip the remaining steps.
5051. If the tag returns a 404, the client MUST begin with an empty image index.
5061. Verify the descriptor for the manifest is not already in the referrers list (duplicate entries SHOULD NOT be created).
5071. Append a descriptor for the pushed manifest to the manifests in the referrers list.
508 The value of the `artifactType` MUST be set to the `artifactType` value in the pushed manifest, if present.
509 If the `artifactType` is empty or missing in a pushed image manifest, the value of `artifactType` MUST be set to the config descriptor `mediaType` value.
510 All annotations from the pushed manifest MUST be copied to this descriptor.
5111. Push the updated referrers list using the same [referrers tag schema](#referrers-tag-schema).
512 The client MAY use conditional HTTP requests to prevent overwriting a referrers list that has changed since it was first pulled.
513
514#### Content Discovery
515
516##### Listing Tags
517
518To fetch the list of tags, perform a `GET` request to a path in the following format: `/v2/<name>/tags/list` <sup>[end-8a](#endpoints)</sup>
519
520`<name>` is the namespace of the repository.
521Assuming a repository is found, this request MUST return a `200 OK` response code.
522The list of tags MAY be empty if there are no tags on the repository.
523If the list is not empty, the tags MUST be in lexical order (i.e. case-insensitive alphanumeric order).
524
525Upon success, the response MUST be a json body in the following format:
526```json
527{
528 "name": "<name>",
529 "tags": [
530 "<tag1>",
531 "<tag2>",
532 "<tag3>"
533 ]
534}
535```
536
537`<name>` is the namespace of the repository, and `<tag1>`, `<tag2>`, and `<tag3>` are each tags on the repository.
538
539In addition to fetching the whole list of tags, a subset of the tags can be fetched by providing the `n` query parameter.
540In this case, the path will look like the following: `/v2/<name>/tags/list?n=<int>` <sup>[end-8b](#endpoints)</sup>
541
542`<name>` is the namespace of the repository, and `<int>` is an integer specifying the number of tags requested.
543The response to such a request MAY return fewer than `<int>` results, but only when the total number of tags attached to the repository is less than `<int>` or a `Link` header is provided.
544Otherwise, the response MUST include `<int>` results.
545A `Link` header MAY be included in the response when additional tags are available.
546If included, the `Link` header MUST be set according to [RFC5988](https://www.rfc-editor.org/rfc/rfc5988.html) with the Relation Type `rel="next"`.
547When `n` is zero, this endpoint MUST return an empty list, and MUST NOT include a `Link` header.
548Without the `last` query parameter (described next), the list returned will start at the beginning of the list and include `<int>` results.
549As above, the tags MUST be in lexical order.
550
551The `last` query parameter provides further means for limiting the number of tags.
552It is usually used in combination with the `n` parameter: `/v2/<name>/tags/list?n=<int>&last=<tagname>` <sup>[end-8b](#endpoints)</sup>
553
554`<name>` is the namespace of the repository, `<int>` is the number of tags requested, and `<tagname>` is the *value* of the last tag.
555`<tagname>` MUST NOT be a numerical index, but rather it MUST be a proper tag.
556A request of this sort will return up to `<int>` tags, beginning non-inclusively with `<tagname>`.
557That is to say, `<tagname>` will not be included in the results, but up to `<int>` tags *after* `<tagname>` will be returned.
558The tags MUST be in lexical order.
559
560When using the `last` query parameter, the `n` parameter is OPTIONAL.
561
562_Implementers note:_
563Previous versions of this specification did not include the `Link` header.
564Clients depending on the number of tags returned matching `n` may prematurely stop pagination on registries using the `Link` header.
565When available, clients should prefer the `Link` header over using the `last` parameter for pagination.
566
567##### Listing Referrers
568
569*Note: this feature was added in distibution-spec 1.1.
570Registries should see [Enabling the Referrers API](#enabling-the-referrers-api) before enabling this.*
571
572To fetch the list of referrers, perform a `GET` request to a path in the following format: `/v2/<name>/referrers/<digest>` <sup>[end-12a](#endpoints)</sup>.
573
574`<name>` is the namespace of the repository, and `<digest>` is the digest of the manifest specified in the `subject` field.
575
576Assuming a repository is found, this request MUST return a `200 OK` response code.
577If the registry supports the referrers API, the registry MUST NOT return a `404 Not Found` to a referrers API requests.
578If the request is invalid, such as a `<digest>` with an invalid syntax, a `400 Bad Request` MUST be returned.
579
580Upon success, the response MUST be a JSON body with an image index containing a list of descriptors.
581The `Content-Type` header MUST be set to `application/vnd.oci.image.index.v1+json`.
582Each descriptor is of an image manifest or index in the same `<name>` namespace with a `subject` field that specifies the value of `<digest>`.
583The descriptors MUST include an `artifactType` field that is set to the value of the `artifactType` in the image manifest or index, if present.
584If the `artifactType` is empty or missing in the image manifest, the value of `artifactType` MUST be set to the config descriptor `mediaType` value.
585If the `artifactType` is empty or missing in an index, the `artifactType` MUST be omitted.
586The descriptors MUST include annotations from the image manifest or index.
587If a query results in no matching referrers, an empty manifest list MUST be returned.
588
589```json
590{
591 "schemaVersion": 2,
592 "mediaType": "application/vnd.oci.image.index.v1+json",
593 "manifests": [
594 {
595 "mediaType": "application/vnd.oci.image.manifest.v1+json",
596 "size": 1234,
597 "digest": "sha256:a1a1a1...",
598 "artifactType": "application/vnd.example.sbom.v1",
599 "annotations": {
600 "org.opencontainers.image.created": "2022-01-01T14:42:55Z",
601 "org.example.sbom.format": "json"
602 }
603 },
604 {
605 "mediaType": "application/vnd.oci.image.manifest.v1+json",
606 "size": 1234,
607 "digest": "sha256:a2a2a2...",
608 "artifactType": "application/vnd.example.signature.v1",
609 "annotations": {
610 "org.opencontainers.image.created": "2022-01-01T07:21:33Z",
611 "org.example.signature.fingerprint": "abcd"
612 }
613 },
614 {
615 "mediaType": "application/vnd.oci.image.index.v1+json",
616 "size": 1234,
617 "digest": "sha256:a3a3a3...",
618 "annotations": {
619 "org.opencontainers.image.created": "2023-01-01T07:21:33Z",
620 }
621 }
622 ]
623}
624```
625
626A `Link` header MUST be included in the response when the descriptor list cannot be returned in a single manifest.
627Each response is an image index with different descriptors in the `manifests` field.
628The `Link` header MUST be set according to [RFC5988](https://www.rfc-editor.org/rfc/rfc5988.html) with the Relation Type `rel="next"`.
629
630The registry SHOULD support filtering on `artifactType`.
631To fetch the list of referrers with a filter, perform a `GET` request to a path in the following format: `/v2/<name>/referrers/<digest>?artifactType=<artifactType>` <sup>[end-12b](#endpoints)</sup>.
632If filtering is requested and applied, the response MUST include a header `OCI-Filters-Applied: artifactType` denoting that an `artifactType` filter was applied.
633If multiple filters are applied, the header MUST contain a comma separated list of applied filters.
634
635Example request with filtering:
636
637```
638GET /v2/<name>/referrers/<digest>?artifactType=application/vnd.example.sbom.v1
639```
640
641Example response with filtering:
642
643```json
644OCI-Filters-Applied: artifactType
645{
646 "schemaVersion": 2,
647 "mediaType": "application/vnd.oci.image.index.v1+json",
648 "manifests": [
649 {
650 "mediaType": "application/vnd.oci.image.manifest.v1+json",
651 "size": 1234,
652 "digest": "sha256:a1a1a1...",
653 "artifactType": "application/vnd.example.sbom.v1",
654 "annotations": {
655 "org.opencontainers.artifact.created": "2022-01-01T14:42:55Z",
656 "org.example.sbom.format": "json"
657 }
658 }
659 ],
660}
661```
662
663If the [referrers API](#listing-referrers) returns a 404, the client MUST fallback to pulling the [referrers tag schema](#referrers-tag-schema).
664The response SHOULD be an image index with the same content that would be expected from the referrers API.
665If the response to the [referrers API](#listing-referrers) is a 404, and the tag schema does not return a valid image index, the client SHOULD assume there are no referrers to the manifest.
666
667#### Content Management
668
669Content management refers to the deletion of blobs, tags, and manifests.
670Registries MAY implement deletion or they MAY disable it.
671Similarly, a registry MAY implement tag deletion, while others MAY allow deletion only by manifest.
672
673##### Deleting tags
674
675To delete a tag, perform a `DELETE` request to a path in the following format: `/v2/<name>/manifests/<tag>` <sup>[end-9](#endpoints)</sup>
676
677`<name>` is the namespace of the repository, and `<tag>` is the name of the tag to be deleted.
678Upon success, the registry MUST respond with a `202 Accepted` code.
679If tag deletion is disabled, the registry MUST respond with either a `400 Bad Request` or a `405 Method Not Allowed`.
680
681Once deleted, a `GET` to `/v2/<name>/manifests/<tag>` will return a 404.
682
683##### Deleting Manifests
684
685To delete a manifest, perform a `DELETE` request to a path in the following format: `/v2/<name>/manifests/<digest>` <sup>[end-9](#endpoints)</sup>
686
687`<name>` is the namespace of the repository, and `<digest>` is the digest of the manifest to be deleted.
688Upon success, the registry MUST respond with a `202 Accepted` code.
689If the repository does not exist, the response MUST return `404 Not Found`.
690If manifest deletion is disabled, the registry MUST respond with either a `400 Bad Request` or a `405 Method Not Allowed`.
691
692Once deleted, a `GET` to `/v2/<name>/manifests/<digest>` and any tag pointing to that digest will return a 404.
693
694When deleting an image manifest that contains a `subject` field, and the [referrers API](#listing-referrers) returns a 404, clients SHOULD:
695
6961. Pull the referrers list using the [referrers tag schema](#referrers-tag-schema).
6971. Remove the descriptor entry from the array of manifests that references the deleted manifest.
6981. Push the updated referrers list using the same [referrers tag schema](#referrers-tag-schema).
699 The client MAY use conditional HTTP requests to prevent overwriting an referrers list that has changed since it was first pulled.
700
701When deleting a manifest that has an associated [referrers tag schema](#referrers-tag-schema), clients MAY also delete the referrers tag when it returns a valid image index.
702
703##### Deleting Blobs
704
705To delete a blob, perform a `DELETE` request to a path in the following format: `/v2/<name>/blobs/<digest>` <sup>[end-10](#endpoints)</sup>
706
707`<name>` is the namespace of the repository, and `<digest>` is the digest of the blob to be deleted.
708Upon success, the registry MUST respond with code `202 Accepted`.
709If the blob is not found, a `404 Not Found` code MUST be returned.
710If blob deletion is disabled, the registry MUST respond with either a `400 Bad Request` or a `405 Method Not Allowed`.
711
712### Backwards Compatibility
713
714Client implementations MUST support registries that implement partial or older versions of the OCI Distribution Spec.
715This section describes client fallback procedures that MUST be implemented when a new/optional API is not available from a registry.
716
717#### Unavailable Referrers API
718
719A client that pushes an image manifest with a defined `subject` field MUST verify the [referrers API](#listing-referrers) is available or fallback to updating the image index pushed to a tag described by the [referrers tag schema](#referrers-tag-schema).
720A client querying the [referrers API](#listing-referrers) and receiving a `404 Not Found` MUST fallback to using an image index pushed to a tag described by the [referrers tag schema](#referrers-tag-schema).
721
722##### Referrers Tag Schema
723
724```text
725<alg>-<ref>
726```
727
728- `<alg>`: the digest algorithm (e.g. `sha256` or `sha512`)
729- `<ref>`: the digest from the `subject` field (limit of 64 characters)
730
731For example, a manifest with the `subject` field digest set to `sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` in the `registry.example.org/project` repository would have a descriptor in the referrers list at `registry.example.org/project:sha256-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`.
732
733This tag should return an image index matching the expected response of the [referrers API](#listing-referrers).
734Maintaining the content of this tag is the responsibility of clients pushing and deleting image manifests that contain a `subject` field.
735
736*Note*: multiple clients could attempt to update the tag simultaneously resulting in race conditions and data loss.
737Protection against race conditions is the responsibility of clients and end users, and can be resolved by using a registry that provides the [referrers API](#listing-referrers).
738Clients MAY use a conditional HTTP push for registries that support ETag conditions to avoid conflicts with other clients.
739
740### Upgrade Procedures
741
742The following describes procedures for upgrading to a newer version of the spec and the process to enable new APIs.
743
744#### Enabling the Referrers API
745
746The referrers API here is described by [Listing Referrers](#listing-referrers) and [end-12a](#endpoints).
747When registries add support for the referrers API, this API needs to account for manifests that were pushed before the API was available using the [Referrers Tag Schema](#referrers-tag-schema).
748
7491. Registries MUST include preexisting image manifests that are listed in an image index tagged with the [referrers tag schema](#referrers-tag-schema) and have a valid `subject` field in the referrers API response.
7501. Registries MAY include all preexisting image manifests with a `subject` field in the referrers API response.
7511. After the referrers API is enabled, Registries MUST include all newly pushed image manifests with a valid `subject` field in the referrers API response.
752
753### API
754
755The API operates over HTTP. Below is a summary of the endpoints used by the API.
756
757#### Determining Support
758
759To check whether or not the registry implements this specification, perform a `GET` request to the following endpoint: `/v2/` <sup>[end-1](#endpoints)</sup>.
760
761If the response is `200 OK`, then the registry implements this specification.
762
763This endpoint MAY be used for authentication/authorization purposes, but this is out of the purview of this specification.
764
765#### Endpoints
766
767| ID | Method | API Endpoint | Success | Failure |
768| ------- | -------------- | -------------------------------------------------------------- | ----------- | ----------------- |
769| end-1 | `GET` | `/v2/` | `200` | `404`/`401` |
770| end-2 | `GET` / `HEAD` | `/v2/<name>/blobs/<digest>` | `200` | `404` |
771| end-3 | `GET` / `HEAD` | `/v2/<name>/manifests/<reference>` | `200` | `404` |
772| end-4a | `POST` | `/v2/<name>/blobs/uploads/` | `202` | `404` |
773| end-4b | `POST` | `/v2/<name>/blobs/uploads/?digest=<digest>` | `201`/`202` | `404`/`400` |
774| end-5 | `PATCH` | `/v2/<name>/blobs/uploads/<reference>` | `202` | `404`/`416` |
775| end-6 | `PUT` | `/v2/<name>/blobs/uploads/<reference>?digest=<digest>` | `201` | `404`/`400` |
776| end-7 | `PUT` | `/v2/<name>/manifests/<reference>` | `201` | `404`/`413` |
777| end-8a | `GET` | `/v2/<name>/tags/list` | `200` | `404` |
778| end-8b | `GET` | `/v2/<name>/tags/list?n=<integer>&last=<tagname>` | `200` | `404` |
779| end-9 | `DELETE` | `/v2/<name>/manifests/<reference>` | `202` | `404`/`400`/`405` |
780| end-10 | `DELETE` | `/v2/<name>/blobs/<digest>` | `202` | `404`/`400`/`405` |
781| end-11 | `POST` | `/v2/<name>/blobs/uploads/?mount=<digest>&from=<other_name>` | `201`/`202` | `404` |
782| end-12a | `GET` | `/v2/<name>/referrers/<digest>` | `200` | `404`/`400` |
783| end-12b | `GET` | `/v2/<name>/referrers/<digest>?artifactType=<artifactType>` | `200` | `404`/`400` |
784| end-13 | `GET` | `/v2/<name>/blobs/uploads/<reference>` | `204` | `404` |
785
786#### Error Codes
787
788A `4XX` response code from the registry MAY return a body in any format. If the response body is in JSON format, it MUST
789have the following format:
790
791```json
792 {
793 "errors": [
794 {
795 "code": "<error identifier, see below>",
796 "message": "<message describing condition>",
797 "detail": "<unstructured>"
798 },
799 ...
800 ]
801 }
802```
803
804The `code` field MUST be a unique identifier, containing only uppercase alphabetic characters and underscores.
805The `message` field is OPTIONAL, and if present, it SHOULD be a human readable string or MAY be empty.
806The `detail` field is OPTIONAL and MAY contain arbitrary JSON data providing information the client can use to resolve the issue.
807
808The `code` field MUST be one of the following:
809
810| ID | Code | Description |
811|-------- | ------------------------|------------------------------------------------------------|
812| code-1 | `BLOB_UNKNOWN` | blob unknown to registry |
813| code-2 | `BLOB_UPLOAD_INVALID` | blob upload invalid |
814| code-3 | `BLOB_UPLOAD_UNKNOWN` | blob upload unknown to registry |
815| code-4 | `DIGEST_INVALID` | provided digest did not match uploaded content |
816| code-5 | `MANIFEST_BLOB_UNKNOWN` | manifest references a manifest or blob unknown to registry |
817| code-6 | `MANIFEST_INVALID` | manifest invalid |
818| code-7 | `MANIFEST_UNKNOWN` | manifest unknown to registry |
819| code-8 | `NAME_INVALID` | invalid repository name |
820| code-9 | `NAME_UNKNOWN` | repository name not known to registry |
821| code-10 | `SIZE_INVALID` | provided length did not match content length |
822| code-11 | `UNAUTHORIZED` | authentication required |
823| code-12 | `DENIED` | requested access to the resource is denied |
824| code-13 | `UNSUPPORTED` | the operation is unsupported |
825| code-14 | `TOOMANYREQUESTS` | too many requests |
826
827#### Warnings
828
829Registry implementations MAY include informational warnings in `Warning` headers, as described in [RFC 7234](https://www.rfc-editor.org/rfc/rfc7234#section-5.5).
830
831If included, `Warning` headers MUST specify a `warn-code` of `299` and a `warn-agent` of `-`, and MUST NOT specify a `warn-date` value.
832
833A registry MUST NOT send more than 4096 bytes of warning data from all headers combined.
834
835Example warning headers:
836
837```
838Warning: 299 - "Your auth token will expire in 30 seconds."
839Warning: 299 - "This registry endpoint is deprecated and will be removed soon."
840Warning: 299 - "This image is deprecated and will be removed soon."
841```
842
843If a client receives `Warning` response headers, it SHOULD report the warnings to the user in an unobtrusive way.
844Clients SHOULD deduplicate warnings from multiple associated responses.
845In accordance with RFC 7234, clients MUST NOT take any automated action based on the presence or contents of warnings, only report them to the user.
846
847### Appendix
848
849The following is a list of documents referenced in this spec:
850
851| ID | Title | Description |
852| ------ | ----- | ----------- |
853| apdx-1 | [Docker Registry HTTP API V2](https://github.com/docker/distribution/blob/5cb406d511b7b9163bff9b6439072e4892e5ae3b/docs/spec/api.md) | The original document upon which this spec was based |
854| apdx-1 | [Details](https://github.com/opencontainers/distribution-spec/blob/ef28f81727c3b5e98ab941ae050098ea664c0960/detail.md) | Historical document describing original API endpoints and requests in detail |
855| apdx-2 | [OCI Image Spec - image](https://github.com/opencontainers/image-spec/blob/v1.0.1/manifest.md) | Description of an image manifest, defined by the OCI Image Spec |
856| apdx-3 | [OCI Image Spec - digests](https://github.com/opencontainers/image-spec/blob/v1.0.1/descriptor.md#digests) | Description of digests, defined by the OCI Image Spec |
857| apdx-4 | [OCI Image Spec - config](https://github.com/opencontainers/image-spec/blob/v1.0.1/config.md) | Description of configs, defined by the OCI Image Spec |
858| apdx-5 | [OCI Image Spec - descriptor](https://github.com/opencontainers/image-spec/blob/v1.0.1/descriptor.md) | Description of descriptors, defined by the OCI Image Spec |
859| apdx-6 | [OCI Image Spec - index](https://github.com/opencontainers/image-spec/blob/v1.0.1/image-index.md) | Description of image index, defined by the OCI Image Spec |