<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.32 (Ruby 3.3.0) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

]>


<rfc ipr="trust200902" docName="draft-gondwana-jmap-blobext-02" category="std" consensus="true" submissionType="IETF" updates="8620, 9404" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="JMAP Blob Extended">JMAP Blob Extensions</title>

    <author initials="B." surname="Gondwana" fullname="Bron Gondwana">
      <organization>Fastmail</organization>
      <address>
        <email>brong@fastmailteam.com</email>
      </address>
    </author>

    <date year="2026" month="March" day="17"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 30?>

<t>The JMAP base protocol (RFC8620) provides the ability to upload and download
arbitrary binary data.  This binary data is called a "blob", and can be used
in all other JMAP extensions.</t>

<t>The JMAP blob extension (RFC9404) added additional ways to create and access
blobs by making inline method calls within a standard JMAP request.</t>

<t>This extension adds more methods to work with blobs, including handling large
blobs by processing them in chunks (building on RFC9404's blob construction
support), and providing server-side blob conversion operations: image format
conversion, archive creation and extraction (zip, tar, cpio), compression
and decompression, and delta/patch operations.</t>



    </abstract>



  </front>

  <middle>


<?line 45?>

<section anchor="introduction"><name>Introduction</name>

<t>The JMAP Blob extension (<xref target="JMAP-BLOB"/> — JMAP Blob Management) offers additional
ways to create blobs, and query where they are used.</t>

<t>This extension builds on that work, offering ways to find more information about
the internal structure of the server's blob store in order to work efficiently
with it, and a new Blob/convert method for server-side blob transformations
including image format conversion, archive creation and extraction, compression
and decompression, and delta/patch operations.</t>

<section anchor="conventions-used-in-this-document"><name>Conventions Used in This Document</name>

<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>

<?line -18?>

</section>
</section>
<section anchor="addition-to-the-capabilities-object"><name>Addition to the Capabilities Object</name>

<t>The capabilities object is returned as part of the JMAP Session
object; see <xref target="JMAP-CORE"/>, Section 2.</t>

<t>This document defines an additional capability URI.</t>

<section anchor="urnietfparamsjmapblobext"><name>urn:ietf:params:jmap:blobext</name>

<t>The capability <spanx style="verb">urn:ietf:params:jmap:blobext</spanx> being present in the
"accountCapabilities" property of an account represents support for
these extended properties on that account.  This capability depends
on <spanx style="verb">urn:ietf:params:jmap:blob</spanx> (<xref target="JMAP-BLOB"/>); both <bcp14>MUST</bcp14> be present
in the account's "accountCapabilities" and in the request's <spanx style="verb">using</spanx>
array.  If this capability is present in one or more
"accountCapabilities" properties then the server <bcp14>MUST</bcp14> also include
the key in the "capabilities" property.</t>

<t>The value of this property in the JMAP session "capabilities"
property <bcp14>MUST</bcp14> be an empty object.</t>

<t>The value of this property in an account's "accountCapabilities"
property is an object that <bcp14>MUST</bcp14> contain the following information
on server capabilities and permissions for that account:</t>

<t><list style="symbols">
  <t>resumableUploadUrl: "String|null"  <vspace blankLines='1'/>
If present, a <xref target="URI-TEMPLATE"/> which supports <xref target="HTTP-RESUMABLE-UPLOADS"/>.
  This <bcp14>MAY</bcp14> be the same as the uploadUrl, and has the same keys.</t>
  <t>chunkSize: "UnsignedInt|null"  <vspace blankLines='1'/>
A hint indicating the preferred chunk size in octets.  If a
  client uploads blobs with exactly this size except for the
  final chunk, and uses Blob/upload with DataSourceObjects
  referencing these chunks, the server can optimise storage of
  these chunks.  Servers <bcp14>MUST</bcp14> allow other sizes for the
  individual data blocks in Blob/upload though, and will then
  choose whether to store them as an array of blobs still, or
  to combine them.</t>
  <t>supportedImageTypes: "String[]"  <vspace blankLines='1'/>
The media types (<xref target="MEDIA-TYPES"/>) supported for ImageConvertRecipe.</t>
  <t>supportedArchiveTypes: "String[]"  <vspace blankLines='1'/>
The archive MIME types supported for ArchiveRecipe and UnArchiveRecipe.
  Defined values are "application/zip", "application/x-tar", and
  "application/x-cpio".</t>
  <t>supportedCompressionTypes: "String[]"  <vspace blankLines='1'/>
The compression MIME types supported for CompressRecipe and
  UnCompressRecipe.  Defined values are "application/gzip",
  "application/x-bzip2", "application/x-xz", and "application/zstd".</t>
  <t>supportedPatchTypes: "String[]"  <vspace blankLines='1'/>
The delta/patch media types supported for DeltaRecipe and
  PatchRecipe.  Defined values are "application/x-rdiff-delta",
  "application/x-bsdiff", and "text/x-diff" (unified diff).
  An empty array means no delta/patch operations are supported.</t>
  <t>maxConvertSize: "UnsignedInt|null"  <vspace blankLines='1'/>
If supplied, the maximum size in octets of any single input
  blob to a Blob/convert operation.  Requests referencing a blob
  larger than this value <bcp14>MUST</bcp14> be rejected with a "tooLarge"
  SetError.  If null, the server does not advertise a specific
  limit but <bcp14>MAY</bcp14> still reject blobs that are too large.</t>
  <t>maxArchiveEntries: "UnsignedInt|null"  <vspace blankLines='1'/>
If supplied, the maximum number of entries allowed in an
  ArchiveRecipe.  Requests exceeding this limit <bcp14>MUST</bcp14> be rejected
  with a "tooLarge" SetError.  If null, the server does not
  advertise a specific limit but <bcp14>MAY</bcp14> still reject requests with
  too many entries.</t>
  <t>maxImageDimension: "UnsignedInt|null"  <vspace blankLines='1'/>
If supplied, the maximum value accepted for <spanx style="verb">width</spanx> or <spanx style="verb">height</spanx>
  in an ImageConvertRecipe, in pixels.  Requests exceeding this
  limit <bcp14>MUST</bcp14> be rejected with a "tooLarge" SetError.  If null,
  the server does not advertise a specific limit but <bcp14>MAY</bcp14> still
  reject requests with dimensions that are too large.</t>
</list></t>

<section anchor="capability-example"><name>Capability Example</name>

<figure><sourcecode type="json"><![CDATA[
{
  "urn:ietf:params:jmap:blobext": {
    "resumableUploadUrl": null,
    "chunkSize": 5242880,
    "supportedImageTypes": [
      "image/png",
      "image/jpeg",
      "image/gif"
    ],
    "supportedArchiveTypes": [
      "application/zip",
      "application/x-tar"
    ],
    "supportedCompressionTypes": [
      "application/gzip",
      "application/x-bzip2",
      "application/zstd"
    ],
    "supportedPatchTypes": [
      "application/x-rdiff-delta",
      "text/x-diff"
    ],
    "maxConvertSize": 104857600,
    "maxArchiveEntries": 10000,
    "maxImageDimension": 8192
  }
}
]]></sourcecode></figure>

</section>
</section>
<section anchor="additions-to-blobget"><name>Additions to Blob/get</name>

<t>When this capability is present, Blob/get accepts an additional
request argument:</t>

<t><list style="symbols">
  <t>dataSourceProperties: "String[]" (default: ["blobId", "size"])
If supplied, only the properties listed in the array are returned
for each DataSourceObject in the <spanx style="verb">chunks</spanx> array.  If omitted, the
default of <spanx style="verb">["blobId", "size"]</spanx> is used.  Available properties
include <spanx style="verb">blobId</spanx>, <spanx style="verb">size</spanx>, <spanx style="verb">offset</spanx>, <spanx style="verb">length</spanx>, <spanx style="verb">position</spanx>, and
<spanx style="verb">digest:*</spanx> values (e.g. <spanx style="verb">digest:sha-256</spanx>).</t>
</list></t>

<t>Blob/get also returns an additional response property (returned by
default when this capability is included in <spanx style="verb">using</spanx>):</t>

<t><list style="symbols">
  <t>chunks: "DataSourceObject[]"  <vspace blankLines='1'/>
An array of one or more data source objects (as defined in <xref target="JMAP-BLOB"/>,
  Section 4.2).  The blob is reconstructed by concatenating the data
  from each data source object in the listed order.  While it is
  expected that each data source object will reference the entire
  underlying chunk blob, the server <bcp14>MAY</bcp14> return offset and length values
  that select only a portion of a chunk's blob.  The client <bcp14>MUST</bcp14> use
  the offset and length to determine which octets to read from each
  chunk.</t>
</list></t>

</section>
<section anchor="additions-to-datasourceobject"><name>Additions to DataSourceObject</name>

<t>When this capability is present, the DataSourceObject (as defined in
<xref target="JMAP-BLOB"/>, Section 4.2) is extended with the following additional
properties.  These apply both to the <spanx style="verb">chunks</spanx> returned by Blob/get
and to DataSourceObjects used in Blob/upload.  The <spanx style="verb">offset</spanx> and
<spanx style="verb">length</spanx> properties are already defined in <xref target="JMAP-BLOB"/>; they are
listed here to document their use in the <spanx style="verb">chunks</spanx> response context,
where they describe the range of each chunk's underlying data source
that contributes to the containing blob.</t>

<t><list style="symbols">
  <t>offset: "UnsignedInt|null"
The offset within the data source from which to start copying
octets (see <xref target="JMAP-BLOB"/>).  <bcp14>MUST</bcp14> fit within the data source
(i.e. offset <bcp14>MUST</bcp14> be less than or equal to the data source size).
If null, defaults to 0 (the start of the data source).</t>
  <t>length: "UnsignedInt|null"
The number of octets to copy from the data source (see
<xref target="JMAP-BLOB"/>).  <bcp14>MUST</bcp14> fit within the data source (i.e. offset +
length <bcp14>MUST</bcp14> be less than or equal to the data source size).  If
null, copy from <spanx style="verb">offset</spanx> to the end of the data source.</t>
  <t>size: "UnsignedInt|null"
The full size of the chunk's underlying data source in octets.</t>
  <t>position: "UnsignedInt|null"
The byte offset of the start of this chunk within the outer
(containing) blob.</t>
</list></t>

<t>If a <spanx style="verb">digest:*</spanx> property (e.g. <spanx style="verb">digest:sha</spanx>, <spanx style="verb">digest:sha-256</spanx>) is
included in <spanx style="verb">dataSourceProperties</spanx>, each DataSourceObject in the
<spanx style="verb">chunks</spanx> array will include the corresponding digest value computed
over the octets that this chunk contributes (i.e. after applying
<spanx style="verb">offset</spanx> and <spanx style="verb">length</spanx>).</t>

<t>When a server provides <spanx style="verb">size</spanx>, <spanx style="verb">position</spanx>, or <spanx style="verb">digest:*</spanx> values in
a Blob/get response, it <bcp14>MUST</bcp14> calculate them correctly.  When a
DataSourceObject containing <spanx style="verb">size</spanx>, <spanx style="verb">position</spanx>, or <spanx style="verb">digest:*</spanx> values
is used in Blob/upload, the server <bcp14>MUST</bcp14> reject the object if any
provided value does not match the actual data.</t>

</section>
<section anchor="additions-to-blobupload"><name>Additions to Blob/upload</name>

<t>When this capability is present, Blob/upload (<xref target="JMAP-BLOB"/>, Section 4)
gains the following additional request property:</t>

<t><list style="symbols">
  <t>noPersist: "Boolean" (default: false)
If true, blobs created by this call are ephemeral: they may be
referenced via creation id backreferences within the same JMAP
request, but the server is not required to persist them beyond the
lifetime of the request.  The server <bcp14>MAY</bcp14> omit ephemeral blobs from
the <spanx style="verb">created</spanx> map of the response and from the <spanx style="verb">createdIds</spanx> of the
final Response object if it did not create a referenceable blob.
This allows servers to optimise pipelines where intermediate blobs
are never needed after the request completes.</t>
</list></t>

</section>
<section anchor="the-expires-response-property"><name>The "expires" response property</name>

<t>When this capability is present, the following blob creation
responses <bcp14>MAY</bcp14> include an additional property: the
resumableUploadUrl response, the Blob/upload response
(<xref target="JMAP-BLOB"/>, Section 4), and the Blob/convert response defined
below.</t>

<t><list style="symbols">
  <t>expires: "UTCDate|null"
A hint from the server indicating the likely availability of
the blob.  The blob is likely to remain available until this
time, and likely not to be available after it.  This is not a
guarantee in either direction: the server <bcp14>MAY</bcp14> garbage collect
the blob before this time if it is unreferenced, and <bcp14>MAY</bcp14>
retain it longer.  If null or absent, the server provides no
hint about the blob's lifetime.</t>
</list></t>

<t>Clients that need the blob to persist beyond the <spanx style="verb">expires</spanx> time
should reference it from a persistent object (e.g., a FileNode
or an Email) before it expires.</t>

</section>
<section anchor="new-method-blobconvert"><name>New method Blob/convert</name>

<t>Blob/convert is defined under the <spanx style="verb">urn:ietf:params:jmap:blobext</spanx>
capability and requires that capability in the request's <spanx style="verb">using</spanx>
array.</t>

<t>Blob/convert performs server-side transformations on blobs.  Like
Blob/upload (<xref target="JMAP-BLOB"/>, Section 4), it takes an <spanx style="verb">accountId</spanx> and a
<spanx style="verb">create</spanx> argument that maps creation ids to conversion request objects.</t>

<t>Each conversion request object <bcp14>MAY</bcp14> also include the following property:</t>

<t><list style="symbols">
  <t>noPersist: "Boolean" (default: false)
If true, the resulting blob is ephemeral: it may be referenced via
creation id backreferences within the same JMAP request, but the
server is not required to persist it beyond the lifetime of the
request.  The server <bcp14>MAY</bcp14> omit ephemeral blobs from the <spanx style="verb">created</spanx>
map of the response and from the <spanx style="verb">createdIds</spanx> of the final Response
object if it did not create a referenceable blob.</t>
</list></t>

<t>Each conversion request object <bcp14>MUST</bcp14> contain exactly one of the
following properties, which determines the type of conversion:</t>

<t><list style="symbols">
  <t>imageConvert: ImageConvertRecipe</t>
  <t>archive: ArchiveRecipe</t>
  <t>unArchive: UnArchiveRecipe</t>
  <t>compress: CompressRecipe</t>
  <t>unCompress: UnCompressRecipe</t>
  <t>delta: DeltaRecipe</t>
  <t>patch: PatchRecipe</t>
</list></t>

<t>The response has the same structure as Blob/upload (<xref target="JMAP-BLOB"/>,
Section 4): a <spanx style="verb">created</spanx> map of creation id to an object containing
<spanx style="verb">id</spanx>, <spanx style="verb">type</spanx>, and <spanx style="verb">size</spanx> for each successful conversion, and a
<spanx style="verb">notCreated</spanx> map of creation id to a SetError object for each failed
conversion.  The <spanx style="verb">id</spanx> is the blobId of the created blob.  The server
<bcp14>MAY</bcp14> also return an <spanx style="verb">expires</spanx> property (see "The expires response
property" above).  Creation id backreferences (using the <spanx style="verb">#</spanx> prefix)
resolve to this <spanx style="verb">id</spanx> and may be used in subsequent conversions within
the same Blob/convert call or in later method calls within the same
JMAP request.</t>

<t>A server <bcp14>MAY</bcp14> return a blobId for a conversion result without
immediately generating the output data.  In this case the server
<bcp14>MUST</bcp14> generate the data when the blob is later accessed (e.g., via
a download request or as input to another operation).  This allows
the server to respond quickly to Blob/convert requests while
deferring expensive work such as image resizing or archive
creation.  The returned blobId <bcp14>MUST</bcp14> be usable in all contexts
where a regular blobId is accepted.  If the deferred generation
later fails (e.g., the source blob has expired), the server
<bcp14>SHOULD</bcp14> return an appropriate HTTP error when the blob is
downloaded.  If the exact size of the output is not yet known, the
server <bcp14>MUST</bcp14> omit the <spanx style="verb">size</spanx> property from the response for that
creation.  If a client later requests the <spanx style="verb">size</spanx> property via
Blob/get for a deferred blob, the server <bcp14>MUST</bcp14> generate the blob
at that point and return the actual size.</t>

<t>The server <bcp14>MUST</bcp14> resolve the order of dependencies between entries
in the <spanx style="verb">create</spanx> map and process them in an order such that all
backreferences are satisfied.  If a dependency cycle is detected,
all members of the cycle <bcp14>MUST</bcp14> be rejected with an
"invalidProperties" error.</t>

<section anchor="imageconvertrecipe"><name>ImageConvertRecipe</name>

<t>An ImageConvertRecipe converts an image blob to a different format
or size.  It is an object with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the source image.</t>
  <t>type: "String"
Media type (<xref target="MEDIA-TYPES"/>) of the image to create (e.g.
"image/png").  <bcp14>MUST</bcp14> be one of the values in the server's
<spanx style="verb">supportedImageTypes</spanx> capability.</t>
  <t>width: "UnsignedInt|null"
Maximum width in pixels of the image to create.  If null, the
server preserves the source width (or scales proportionally if
only <spanx style="verb">height</spanx> is given).</t>
  <t>height: "UnsignedInt|null"
Maximum height in pixels of the image to create.  If null, the
server preserves the source height (or scales proportionally if
only <spanx style="verb">width</spanx> is given).</t>
  <t>ignoreAspect: "Boolean|null"
If true, resize to exactly the given width and height, even if
the aspect ratio is changed.  If null or false, the image is
scaled to fit within the given dimensions while preserving the
aspect ratio.</t>
  <t>quality: "UnsignedInt|null"
Compression quality for lossy formats, as a value from 1 (lowest
quality, smallest file) to 100 (highest quality, largest file).
Only meaningful for formats that support lossy compression such as
image/jpeg and image/webp.  If null, the server selects a sensible
default.</t>
  <t>colorSpace: "String|null"
The color space for the output image.  Defined values are "sRGB"
and "grayscale".  If null, the server preserves the source image's
color space where possible.</t>
  <t>background: "String|null"
A fill color to use when the source image has transparency but the
target format does not support it (e.g. converting PNG to JPEG).
The value is a CSS-style hex color string (e.g. "#ffffff" for white).
If null, the server selects a sensible default (typically white).</t>
  <t>stripMetadata: "Boolean|null"
If true, strip image metadata such as EXIF, XMP, and IPTC data from
the output.  If null or false, the server preserves metadata where
the target format supports it.</t>
  <t>autoOrient: "Boolean|null"
If true, automatically rotate and flip the image according to its
EXIF orientation tag, then reset the tag.  If null or false, the
image data is not reoriented.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — the referenced blobId does not exist.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedImageTypes</spanx>, or
the source blob is not a supported image format.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>, or the
requested dimensions exceed <spanx style="verb">maxImageDimension</spanx>.</t>
</list></t>

</section>
<section anchor="archiverecipe"><name>ArchiveRecipe</name>

<t>An ArchiveRecipe creates an archive blob from a list of entries.
It is an object with the following properties:</t>

<t><list style="symbols">
  <t>type: "String"
The MIME type of the archive to create.  <bcp14>MUST</bcp14> be one of the values
in the server's <spanx style="verb">supportedArchiveTypes</spanx> capability.  Defined values
are "application/zip", "application/x-tar", and "application/x-cpio".</t>
  <t>entries: "ArchiveEntry[]"
An array of ArchiveEntry objects describing the contents of the
archive.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — a referenced entry blobId does not exist.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedArchiveTypes</spanx>;
an entry has an unsupported entryType for the archive format; or
a required field (e.g. linkTarget for symlink entries) is missing.</t>
  <t>"tooLarge" — the number of entries exceeds <spanx style="verb">maxArchiveEntries</spanx>,
or a referenced blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
</list></t>

<section anchor="archiveentry"><name>ArchiveEntry</name>

<t>An ArchiveEntry describes a single entry in an archive.  It is used
both as input (in ArchiveRecipe) and as output (in UnArchiveRecipe
results).  It is an object with the following properties:</t>

<t><list style="symbols">
  <t>name: "String"
The path of the entry within the archive.  Directory entries <bcp14>MUST</bcp14>
have a name ending with "/".</t>
  <t>blobId: "BlobId|null"
The blobId of the content for this entry.  <bcp14>MUST</bcp14> be non-null for
file entries.  <bcp14>MUST</bcp14> be null or absent for directory, symlink,
hardlink, fifo, and device entries.  Violating these constraints
is an "invalidProperties" error.</t>
  <t>entryType: "String|null"
The type of the entry.  If null, defaults to "file".  Defined values
are "file" (a regular file, the default), "directory", "symlink"
(a symbolic link), "hardlink" (a hard link), "fifo" (a named pipe),
"blockDevice" (a block device node), and "charDevice" (a character
device node).  The server <bcp14>MUST</bcp14> reject entries with unsupported
types for the chosen archive format with an "invalidProperties"
error.</t>
  <t>modified: "UTCDate|null"
The modification time of the entry as an RFC 3339 timestamp.
If null, defaults to the current server time.</t>
  <t>linkTarget: "String|null"
The target path for symlink and hardlink entries.  <bcp14>MUST</bcp14> be non-null
when entryType is "symlink" or "hardlink".  <bcp14>MUST</bcp14> be null for all
other entry types.</t>
  <t>mode: "String|null"
Unix file permissions as an octal string (e.g. "0755", "0644").
If null, the server chooses a reasonable default.  This is
represented as a string rather than an integer to avoid ambiguity
between octal and decimal interpretation.</t>
  <t>uid: "UnsignedInt|null"
The numeric user ID of the entry owner.</t>
  <t>gid: "UnsignedInt|null"
The numeric group ID of the entry owner.</t>
  <t>ownerName: "String|null"
The user name of the entry owner.</t>
  <t>groupName: "String|null"
The group name of the entry owner.</t>
  <t>devMajor: "UnsignedInt|null"
The major device number for "blockDevice" and "charDevice" entries.</t>
  <t>devMinor: "UnsignedInt|null"
The minor device number for "blockDevice" and "charDevice" entries.</t>
  <t>comment: "String|null"
A comment string for this entry.</t>
  <t>compressionMethod: "String|null"
The per-entry compression method.  Defined values are "store" (no
compression) and "deflate".  If null, the server chooses a
reasonable default.</t>
</list></t>

</section>
<section anchor="considerations-for-applicationzip"><name>Considerations for application/zip</name>

<t>The zip format only supports "file" and "directory" entry types.
The <spanx style="verb">comment</spanx> and <spanx style="verb">compressionMethod</spanx> properties are only meaningful
for zip archives.  The <spanx style="verb">mode</spanx>, <spanx style="verb">uid</spanx>, <spanx style="verb">gid</spanx>, <spanx style="verb">ownerName</spanx>,
<spanx style="verb">groupName</spanx>, <spanx style="verb">devMajor</spanx>, and <spanx style="verb">devMinor</spanx> properties are ignored.</t>

</section>
<section anchor="considerations-for-applicationx-tar"><name>Considerations for application/x-tar</name>

<t>The tar format supports all entry types.  The <spanx style="verb">mode</spanx>, <spanx style="verb">uid</spanx>, <spanx style="verb">gid</spanx>,
<spanx style="verb">ownerName</spanx>, <spanx style="verb">groupName</spanx>, <spanx style="verb">devMajor</spanx>, and <spanx style="verb">devMinor</spanx> properties are
meaningful for tar archives.  The <spanx style="verb">comment</spanx> and <spanx style="verb">compressionMethod</spanx>
properties are ignored.</t>

<t>Tar archives are not inherently compressed.  To create a compressed
tar archive (e.g. a .tar.gz file), first create the tar archive
using ArchiveRecipe, then compress the result using CompressRecipe.
The following example creates a .tar.gz containing three files in a
single Blob/convert call, using a backreference from the archive
creation to the compression step:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "t1": {
      "archive": {
        "type": "application/x-tar",
        "entries": [
          {
            "name": "site/index.html",
            "blobId": "Baaaa",
            "modified": "2026-03-01T12:00:00Z",
            "mode": "0644"
          },
          {
            "name": "site/logo.png",
            "blobId": "Bbbbb",
            "modified": "2026-02-15T09:30:00Z",
            "mode": "0644"
          },
          {
            "name": "site/style.css",
            "blobId": "Bcccc",
            "modified": "2026-03-01T12:00:00Z",
            "mode": "0644"
          }
        ]
      }
    },
    "t2": {
      "compress": {
        "blobId": "#t1",
        "type": "application/gzip"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

</section>
<section anchor="considerations-for-applicationx-cpio"><name>Considerations for application/x-cpio</name>

<t>The cpio format supports all entry types except that <spanx style="verb">ownerName</spanx> and
<spanx style="verb">groupName</spanx> are not supported.  The <spanx style="verb">comment</spanx> and
<spanx style="verb">compressionMethod</spanx> properties are ignored.</t>

</section>
</section>
<section anchor="unarchiverecipe"><name>UnArchiveRecipe</name>

<t>An UnArchiveRecipe extracts the entry listing from an existing archive
blob.  It is an object with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the archive to extract.</t>
  <t>type: "String|null"
The MIME type of the archive format.  If null, the server <bcp14>SHOULD</bcp14>
attempt to auto-detect the format from the blob content (e.g. by
inspecting magic bytes).  If auto-detection fails, the server <bcp14>MUST</bcp14>
return an "unknownFormat" error.</t>
</list></t>

<t>In addition to the standard creation response properties, a
successful UnArchiveRecipe result includes:</t>

<t><list style="symbols">
  <t>entries: "ArchiveEntry[]"
An array of ArchiveEntry objects describing the contents of the
archive.  Each file entry will have a blobId that can be used to
access the content of that entry.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — the referenced blobId does not exist.</t>
  <t>"unknownFormat" — the server could not determine or does not support
the archive format.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedArchiveTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
</list></t>

</section>
<section anchor="compressrecipe"><name>CompressRecipe</name>

<t>A CompressRecipe compresses a blob using a specified compression
algorithm.  It is an object with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the data to compress.</t>
  <t>type: "String"
The MIME type of the compression format to use.  <bcp14>MUST</bcp14> be one of the
values in the server's <spanx style="verb">supportedCompressionTypes</spanx> capability.
Defined values are "application/gzip", "application/x-bzip2",
"application/x-xz", and "application/zstd".</t>
  <t>level: "UnsignedInt|null"
The compression level, where higher values produce smaller output
at the cost of more CPU time.  If null, the server uses the
format's default level.  The valid range depends on the format;
if the requested level is outside the valid range, the server
<bcp14>SHOULD</bcp14> use the nearest valid value.</t>
  <t>checksum: "Boolean|null"
If true, include an integrity checksum in the compressed output.
If null, the server uses the format's default behaviour.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — the referenced blobId does not exist.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedCompressionTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
</list></t>

<section anchor="considerations-for-applicationgzip"><name>Considerations for application/gzip</name>

<t>Compression level ranges from 1 (fastest) to 9 (best compression).
The default is typically 6.  Gzip always includes a CRC-32 checksum;
the <spanx style="verb">checksum</spanx> property is ignored.</t>

</section>
<section anchor="considerations-for-applicationx-bzip2"><name>Considerations for application/x-bzip2</name>

<t>Compression level ranges from 1 (fastest, 100k block size) to 9
(best compression, 900k block size).  The default is typically 9.
Bzip2 always includes a CRC-32 checksum; the <spanx style="verb">checksum</spanx> property is
ignored.</t>

</section>
<section anchor="considerations-for-applicationx-xz"><name>Considerations for application/x-xz</name>

<t>Compression level ranges from 0 (fastest) to 9 (best compression).
The default is typically 6.  Xz always includes an integrity check;
if <spanx style="verb">checksum</spanx> is true the server <bcp14>SHOULD</bcp14> use SHA-256, otherwise CRC-64
is used by default.</t>

</section>
<section anchor="considerations-for-applicationzstd"><name>Considerations for application/zstd</name>

<t>Compression level ranges from 1 (fastest) to 22 (best compression).
The default is typically 3.  If <spanx style="verb">checksum</spanx> is true, an xxHash-64
checksum is included in the frame; the default is false.</t>

</section>
</section>
<section anchor="uncompressrecipe"><name>UnCompressRecipe</name>

<t>An UnCompressRecipe decompresses a compressed blob.  It is an object
with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the compressed data to decompress.</t>
  <t>type: "String|null"
The MIME type of the compression format.  If null, the server <bcp14>SHOULD</bcp14>
attempt to auto-detect the format from magic bytes.  If auto-detection
fails, the server <bcp14>MUST</bcp14> return an "unknownFormat" error.</t>
</list></t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — the referenced blobId does not exist.</t>
  <t>"unknownFormat" — the server could not determine or does not support
the compression format.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedCompressionTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
</list></t>

</section>
<section anchor="deltarecipe"><name>DeltaRecipe</name>

<t>A DeltaRecipe computes a delta between two blobs.  It is an object
with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the original (base) blob.</t>
  <t>newBlobId: "BlobId"
The blobId of the new blob to compare against.</t>
  <t>type: "String"
The media type of the delta format to produce.  <bcp14>MUST</bcp14> be one of the
values in the server's <spanx style="verb">supportedPatchTypes</spanx> capability.</t>
</list></t>

<t>The result blob is the computed delta, which can be applied to the
base blob using PatchRecipe to reconstruct the new blob.</t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — a referenced blobId does not exist.</t>
  <t>"invalidProperties" — the type is not in <spanx style="verb">supportedPatchTypes</spanx>.</t>
  <t>"tooLarge" — a referenced blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
</list></t>

<section anchor="considerations-for-applicationx-rdiff-delta"><name>Considerations for application/x-rdiff-delta</name>

<t>The server computes an rdiff signature of the base blob and then
generates a delta against the new blob.  The resulting delta blob
can only be applied to the exact base blob used to generate it.</t>

</section>
<section anchor="considerations-for-applicationx-bsdiff"><name>Considerations for application/x-bsdiff</name>

<t>The server produces a bsdiff-format patch.  Both blobs must fit in
memory; servers <bcp14>MAY</bcp14> reject very large blobs with a "tooLarge" error.</t>

</section>
<section anchor="considerations-for-textx-diff"><name>Considerations for text/x-diff</name>

<t>The server produces a unified diff.  Both blobs are interpreted as
text.  If either blob contains content that cannot be interpreted as
text, the server <bcp14>MUST</bcp14> return an "unknownFormat" error.</t>

</section>
</section>
<section anchor="patchrecipe"><name>PatchRecipe</name>

<t>A PatchRecipe applies a delta to a base blob to produce a new blob.
It is an object with the following properties:</t>

<t><list style="symbols">
  <t>blobId: "BlobId"
The blobId of the base blob to patch.</t>
  <t>deltaBlobId: "BlobId"
The blobId of the delta to apply.</t>
  <t>deltaType: "String"
The media type of the delta format.  <bcp14>MUST</bcp14> be one of the values in
the server's <spanx style="verb">supportedPatchTypes</spanx> capability.</t>
</list></t>

<t>The result blob is the patched output.</t>

<t>Errors:</t>

<t><list style="symbols">
  <t>"notFound" — a referenced blobId does not exist.</t>
  <t>"invalidProperties" — the deltaType is not in <spanx style="verb">supportedPatchTypes</spanx>.</t>
  <t>"unknownFormat" — the delta blob is not valid for the specified
format (e.g., corrupt or malformed delta data).</t>
  <t>"tooLarge" — a referenced blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
</list></t>

</section>
</section>
</section>
<section anchor="examples"><name>Examples</name>

<section anchor="querying-blob-chunks"><name>Querying Blob Chunks</name>

<t>This example fetches a blob's chunk structure with offsets, sizes,
and SHA-256 digests:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/get", {
  "accountId": "abc",
  "ids": ["B1a2b3c"],
  "dataSourceProperties": [
    "blobId", "size", "offset", "length", "position",
    "digest:sha-256"
  ]
}, "0"]]
]]></sourcecode></figure>

<t>The response shows the blob is stored as two chunks:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/get", {
  "accountId": "abc",
  "list": [{
    "id": "B1a2b3c",
    "size": 10485760,
    "chunks": [
      {
        "blobId": "Bchunk1",
        "size": 5242880,
        "offset": 0,
        "length": 5242880,
        "position": 0,
        "digest:sha-256": "a1b2c3..."
      },
      {
        "blobId": "Bchunk2",
        "size": 5242880,
        "offset": 0,
        "length": 5242880,
        "position": 5242880,
        "digest:sha-256": "d4e5f6..."
      }
    ]
  }],
  "notFound": []
}, "0"]]
]]></sourcecode></figure>

<t>The <spanx style="verb">position</spanx> values show where each chunk fits in the assembled
blob, and the <spanx style="verb">digest:sha-256</spanx> values can be used to verify chunk
integrity.</t>

</section>
<section anchor="creating-a-zip-archive"><name>Creating a Zip Archive</name>

<t>This example creates a zip file containing an HTML document, a CSS
file, and a JPEG image:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "z1": {
      "archive": {
        "type": "application/zip",
        "entries": [
          {
            "name": "site/index.html",
            "blobId": "Baaaa"
          },
          {
            "name": "site/style.css",
            "blobId": "Bbbbb"
          },
          {
            "name": "site/photo.jpg",
            "blobId": "Bcccc"
          }
        ]
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The response includes the blobId, type, and size of the created
archive:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "z1": {
      "id": "B9f2a4e",
      "type": "application/zip",
      "size": 104857
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

</section>
<section anchor="creating-a-compressed-tar-archive"><name>Creating a Compressed Tar Archive</name>

<t>This example creates a .tar.gz file from the same three files.
The intermediate tar blob uses <spanx style="verb">noPersist</spanx> since only the final
compressed result is needed:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "t1": {
      "noPersist": true,
      "archive": {
        "type": "application/x-tar",
        "entries": [
          {
            "name": "site/index.html",
            "blobId": "Baaaa",
            "modified": "2026-03-01T12:00:00Z",
            "mode": "0644"
          },
          {
            "name": "site/style.css",
            "blobId": "Bbbbb",
            "modified": "2026-03-01T12:00:00Z",
            "mode": "0644"
          },
          {
            "name": "site/photo.jpg",
            "blobId": "Bcccc",
            "modified": "2026-02-15T09:30:00Z",
            "mode": "0644"
          }
        ]
      }
    },
    "t2": {
      "compress": {
        "blobId": "#t1",
        "type": "application/gzip"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>Because "t1" was created with <spanx style="verb">noPersist</spanx>, the server may omit it
from the response:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "t2": {
      "id": "Bd81c7f",
      "type": "application/gzip",
      "size": 98304
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

</section>
<section anchor="extracting-a-compressed-tar-archive"><name>Extracting a Compressed Tar Archive</name>

<t>This example decompresses and extracts a .tar.gz file to discover
its contents.  The intermediate decompressed tar blob uses
<spanx style="verb">noPersist</spanx>:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "u1": {
      "noPersist": true,
      "unCompress": {
        "blobId": "Bd81c7f",
        "type": "application/gzip"
      }
    },
    "u2": {
      "unArchive": {
        "blobId": "#u1",
        "type": "application/x-tar"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The response for the UnArchiveRecipe includes the standard creation
response properties plus an <spanx style="verb">entries</spanx> array listing the archive
contents, with a blobId for each file entry:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "u2": {
      "id": "Be3a901",
      "type": "application/x-tar",
      "size": 102400,
      "entries": [
        {
          "name": "site/index.html",
          "blobId": "Bdd001",
          "entryType": "file",
          "modified": "2026-03-01T12:00:00Z",
          "mode": "0644"
        },
        {
          "name": "site/style.css",
          "blobId": "Bdd002",
          "entryType": "file",
          "modified": "2026-03-01T12:00:00Z",
          "mode": "0644"
        },
        {
          "name": "site/photo.jpg",
          "blobId": "Bdd003",
          "entryType": "file",
          "modified": "2026-02-15T09:30:00Z",
          "mode": "0644"
        }
      ]
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

<t>The returned blobIds ("Bdd001", "Bdd002", "Bdd003") can be used
to download individual files or as inputs to further Blob/convert
operations.</t>

</section>
</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<t>All security considerations from <xref target="JMAP-CORE"/> and <xref target="JMAP-BLOB"/> apply
to this document.</t>

<section anchor="resource-consumption"><name>Resource Consumption</name>

<t>Several operations defined in this document can consume significant
server resources.</t>

<t>Archive and compression operations may require substantial CPU and
memory.  Servers <bcp14>SHOULD</bcp14> impose reasonable limits on archive size,
number of entries, nesting depth of archives within archives,
compression ratios (to mitigate zip bomb attacks), and total
processing time.  Servers <bcp14>SHOULD</bcp14> reject requests that would exceed
these limits with a "tooLarge" or "serverFail" error as appropriate.</t>

<t>Image conversion can also consume significant resources, especially
for very large images or high output dimensions.</t>

<t>Delta and patch operations can also be resource-intensive,
particularly for large blobs.  Servers <bcp14>SHOULD</bcp14> impose limits on the
size of blobs that can be used as inputs to these operations.</t>

<t>Servers <bcp14>SHOULD</bcp14> advertise their limits via the <spanx style="verb">maxConvertSize</spanx>,
<spanx style="verb">maxArchiveEntries</spanx>, and <spanx style="verb">maxImageDimension</spanx> capability properties
so that clients can avoid making requests that will be rejected.
Even when these properties are not advertised, servers <bcp14>SHOULD</bcp14> set
sensible internal limits and reject requests that exceed them.</t>

</section>
<section anchor="archive-path-traversal"><name>Archive Path Traversal</name>

<t>Archive formats allow entry names containing path separators and
relative path components such as "../".  Malicious archives may use
names like "../../etc/passwd" to attempt directory traversal.  While
UnArchiveRecipe only returns entry metadata and blob references
(not files on the server filesystem), clients that extract archive
contents to a filesystem <bcp14>MUST</bcp14> validate entry names and reject or
sanitize paths containing ".." components or absolute paths.
Servers <bcp14>SHOULD</bcp14> reject ArchiveRecipe requests containing entry names
with ".." path components.</t>

</section>
<section anchor="content-smuggling"><name>Content Smuggling</name>

<t>The ability to split content into multiple blobs, recombine them via
Blob/upload, and apply delta patches may be used to bypass security
scanners that inspect blob content.  Servers that perform content
scanning <bcp14>SHOULD</bcp14> scan the output of Blob/convert operations as well
as the inputs.</t>

</section>
</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<section anchor="jmap-capability-registration-for-urnietfparamsjmapblobext"><name>JMAP Capability Registration for urn:ietf:params:jmap:blobext</name>

<t>IANA is requested to register the "Blob Extended" Capability as follows:</t>

<t>Capability Name: urn:ietf:params:jmap:blobext</t>

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Specification document: this document</t>

<t>Security and privacy considerations: this document, Security Considerations</t>

</section>
<section anchor="jmap-error-code-registrations"><name>JMAP Error Code Registrations</name>

<t>IANA is requested to register the following entries in the "JMAP
Error Codes" registry:</t>

<section anchor="unknownformat"><name>unknownFormat</name>

<t>JMAP Error Code: unknownFormat</t>

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Description: The server could not determine the format of the blob,
or the detected format is not supported.  This error is returned
when auto-detection of archive or compression format fails, or when
the blob content does not match the specified format.</t>

<t>Reference: this document</t>

</section>
</section>
</section>
<section anchor="changes"><name>Changes</name>

<t>EDITOR: please remove this section before publication.</t>

<t>The source of this document exists on github at: https://github.com/brong/draft-gondwana-jmap-blobext/</t>

<t><strong>draft-gondwana-jmap-blobext-02</strong></t>

<t><list style="symbols">
  <t>Replaced RdiffRecipe with generic DeltaRecipe and PatchRecipe using
media types (rdiff, bsdiff, unified diff).</t>
  <t>Replaced supportsRdiff with supportedPatchTypes capability.</t>
  <t>Clarified chunkSize as a hint, not a definitive statement.</t>
  <t>Added lazy generation text for Blob/convert (deferred output).</t>
  <t>Defined "expires" response property for blob creation responses.</t>
</list></t>

<t><strong>draft-gondwana-jmap-blobext-01</strong></t>

<t><list style="symbols">
  <t>Added Blob/convert method with recipes for image conversion, archiving,
compression, and rdiff.</t>
  <t>Added noPersist option to Blob/upload and Blob/convert for ephemeral
intermediate blobs in pipelines.</t>
  <t>Removed rdiffSignature and rdiffPatch from Blob/get and DataSourceObject.</t>
  <t>Fleshed out capability object with supported type lists.</t>
  <t>Added capability and method examples.</t>
  <t>Expanded Security Considerations.</t>
  <t>Updated IANA registrations with error codes and corrected capability URI.</t>
  <t>Added limit capability properties: maxConvertSize, maxArchiveEntries,
maxImageDimension, and supportsRdiff.</t>
  <t>Added dependency resolution requirement for Blob/convert create map
with cycle detection.</t>
  <t>Now updates both RFC 8620 and RFC 9404.</t>
</list></t>

<t><strong>draft-gondwana-jmap-blobext-00</strong></t>

<t><list style="symbols">
  <t>initial proposal</t>
</list></t>

</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>TODO</t>

<t>{backmatter}</t>

</section>


  </middle>

  <back>



    <references title='Normative References' anchor="sec-normative-references">



<reference anchor="URI-TEMPLATE">
  <front>
    <title>URI Template</title>
    <author fullname="J. Gregorio" initials="J." surname="Gregorio"/>
    <author fullname="R. Fielding" initials="R." surname="Fielding"/>
    <author fullname="M. Hadley" initials="M." surname="Hadley"/>
    <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
    <author fullname="D. Orchard" initials="D." surname="Orchard"/>
    <date month="March" year="2012"/>
    <abstract>
      <t>A URI Template is a compact sequence of characters for describing a range of Uniform Resource Identifiers through variable expansion. This specification defines the URI Template syntax and the process for expanding a URI Template into a URI reference, along with guidelines for the use of URI Templates on the Internet. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="6570"/>
  <seriesInfo name="DOI" value="10.17487/RFC6570"/>
</reference>

<reference anchor="JMAP-CORE">
  <front>
    <title>The JSON Meta Application Protocol (JMAP)</title>
    <author fullname="N. Jenkins" initials="N." surname="Jenkins"/>
    <author fullname="C. Newman" initials="C." surname="Newman"/>
    <date month="July" year="2019"/>
    <abstract>
      <t>This document specifies a protocol for clients to efficiently query, fetch, and modify JSON-based data objects, with support for push notification of changes and fast resynchronisation and for out-of- band binary data upload/download.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8620"/>
  <seriesInfo name="DOI" value="10.17487/RFC8620"/>
</reference>

<reference anchor="JMAP-BLOB">
  <front>
    <title>JSON Meta Application Protocol (JMAP) Blob Management Extension</title>
    <author fullname="B. Gondwana" initials="B." role="editor" surname="Gondwana"/>
    <date month="August" year="2023"/>
    <abstract>
      <t>The JSON Meta Application Protocol (JMAP) base protocol (RFC 8620) provides the ability to upload and download arbitrary binary data via HTTP POST and GET on a defined endpoint. This binary data is called a "blob".</t>
      <t>This extension adds additional ways to create and access blobs by making inline method calls within a standard JMAP request.</t>
      <t>This extension also adds a reverse lookup mechanism to discover where blobs are referenced within other data types.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9404"/>
  <seriesInfo name="DOI" value="10.17487/RFC9404"/>
</reference>

<reference anchor="MEDIA-TYPES">
  <front>
    <title>Media Type Specifications and Registration Procedures</title>
    <author fullname="N. Freed" initials="N." surname="Freed"/>
    <author fullname="J. Klensin" initials="J." surname="Klensin"/>
    <author fullname="T. Hansen" initials="T." surname="Hansen"/>
    <date month="January" year="2013"/>
    <abstract>
      <t>This document defines procedures for the specification and registration of media types for use in HTTP, MIME, and other Internet protocols. This memo documents an Internet Best Current Practice.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="13"/>
  <seriesInfo name="RFC" value="6838"/>
  <seriesInfo name="DOI" value="10.17487/RFC6838"/>
</reference>


<reference anchor="HTTP-RESUMABLE-UPLOADS">
   <front>
      <title>Resumable Uploads for HTTP</title>
      <author fullname="Marius Kleidl" initials="M." surname="Kleidl">
         <organization>Transloadit</organization>
      </author>
      <author fullname="Guoye Zhang" initials="G." surname="Zhang">
         <organization>Apple Inc.</organization>
      </author>
      <author fullname="Lucas Pardue" initials="L." surname="Pardue">
         <organization>Cloudflare</organization>
      </author>
      <date day="2" month="March" year="2026"/>
      <abstract>
	 <t>   HTTP data transfers can encounter interruption due to reasons such as
   canceled requests or dropped connections.  If the intended recipient
   can indicate how much of the data was received prior to interruption,
   a sender can resume data transfer at that point instead of attempting
   to transfer all of the data again.  HTTP range requests support this
   concept of resumable downloads from server to client.  This document
   describes a mechanism that supports resumable uploads from client to
   server using HTTP.

	 </t>
      </abstract>
   </front>
   <seriesInfo name="Internet-Draft" value="draft-ietf-httpbis-resumable-upload-11"/>
   
</reference>

<reference anchor="RFC2119">
  <front>
    <title>Key words for use in RFCs to Indicate Requirement Levels</title>
    <author fullname="S. Bradner" initials="S." surname="Bradner"/>
    <date month="March" year="1997"/>
    <abstract>
      <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="2119"/>
  <seriesInfo name="DOI" value="10.17487/RFC2119"/>
</reference>

<reference anchor="RFC8174">
  <front>
    <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
    <author fullname="B. Leiba" initials="B." surname="Leiba"/>
    <date month="May" year="2017"/>
    <abstract>
      <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="8174"/>
  <seriesInfo name="DOI" value="10.17487/RFC8174"/>
</reference>




    </references>





  </back>

<!-- ##markdown-source:
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
OwAs0JCvPkf/CdAV4QVjkQAA

-->

</rfc>

