<?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-ietf-jmap-blobext-00" 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="April" day="13"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 29?>

<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 44?>

<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>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>supportedImageReadTypes: "String[]|null"  <vspace blankLines='1'/>
The media types (<xref target="MEDIA-TYPES"/>) that the server can read as
  input to ImageConvertRecipe.  If null, the server does not
  support image conversion.</t>
  <t>supportedImageWriteTypes: "String[]|null"  <vspace blankLines='1'/>
The media types (<xref target="MEDIA-TYPES"/>) that the server can produce
  as output from ImageConvertRecipe.  If null, the server does
  not support image conversion.</t>
  <t>supportedArchiveTypes: "String[]|null"  <vspace blankLines='1'/>
The archive MIME types supported for creating archives via
  ArchiveRecipe.  Defined values are "application/zip",
  "application/x-tar", and "application/x-cpio".  If null,
  the server does not support archive creation.</t>
  <t>supportedExtractTypes: "String[]|null"  <vspace blankLines='1'/>
The archive MIME types supported for extracting archives via
  ExtractRecipe.  This <bcp14>MAY</bcp14> include types not in
  <spanx style="verb">supportedArchiveTypes</spanx> (e.g., "application/vnd.ms-tnef").
  If null, the server does not support archive extraction.</t>
  <t>supportedCompressTypes: "String[]|null"  <vspace blankLines='1'/>
The compression MIME types supported for compressing via
  CompressRecipe.  Defined values are "application/gzip",
  "application/x-bzip2", "application/x-xz", and
  "application/zstd".  If null, the server does not support
  compression.</t>
  <t>supportedDecompressTypes: "String[]|null"  <vspace blankLines='1'/>
The compression MIME types supported for decompressing via
  DecompressRecipe.  This <bcp14>MAY</bcp14> include types not in
  <spanx style="verb">supportedCompressTypes</spanx>.  If null, the server does not
  support decompression.</t>
  <t>supportedDeltaTypes: "String[]|null"  <vspace blankLines='1'/>
The delta media types supported for computing deltas via
  DeltaRecipe.  Defined values are
  "application/x-rdiff-delta", "application/x-bsdiff", and
  "text/x-diff" (unified diff).  If null, the server does
  not support delta computation.</t>
  <t>supportedPatchTypes: "String[]|null"  <vspace blankLines='1'/>
The delta media types supported for applying patches via
  PatchRecipe.  This <bcp14>MAY</bcp14> include types not in
  <spanx style="verb">supportedDeltaTypes</spanx>.  If null, the server does not
  support patch application.</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": {
    "chunkSize": 5242880,
    "supportedImageReadTypes": [
      "image/png",
      "image/jpeg",
      "image/gif",
      "image/tiff"
    ],
    "supportedImageWriteTypes": [
      "image/png",
      "image/jpeg"
    ],
    "supportedArchiveTypes": [
      "application/zip",
      "application/x-tar"
    ],
    "supportedExtractTypes": [
      "application/zip",
      "application/x-tar",
      "application/vnd.ms-tnef"
    ],
    "supportedCompressTypes": [
      "application/gzip",
      "application/zstd"
    ],
    "supportedDecompressTypes": [
      "application/gzip",
      "application/x-bzip2",
      "application/zstd"
    ],
    "supportedDeltaTypes": [
      "application/x-rdiff-delta",
      "text/x-diff"
    ],
    "supportedPatchTypes": [
      "application/x-rdiff-delta",
      "text/x-diff"
    ],
    "maxConvertSize": 104857600,
    "maxArchiveEntries": 10000,
    "maxImageDimension": 8192
  }
}
]]></sourcecode></figure>

</section>
</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-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 where <spanx style="verb">*</spanx> is a hash algorithm name from the
IANA "Hash Function Textual Names" registry (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>

<t>Blob/get also accepts the following additional property in
the <spanx style="verb">properties</spanx> array:</t>

<t><list style="symbols">
  <t>imageData: "ImageData|null" (server-set)  <vspace blankLines='1'/>
If the blob is an image or video type and the server can
  extract metadata, this is an ImageData object.  Otherwise
  null.  Only returned if explicitly requested in
  <spanx style="verb">properties</spanx>.  The server <bcp14>MAY</bcp14> need to read the blob content
  to compute this data, so clients <bcp14>SHOULD</bcp14> only request it
  when needed.  Since blobs are immutable, the result for a
  given blobId will never change, and the server <bcp14>SHOULD</bcp14> cache
  it.  <vspace blankLines='1'/>
An ImageData object has the following properties:  <list style="symbols">
      <t>width: "UnsignedInt|null"
Width of the image in pixels, if known.</t>
      <t>height: "UnsignedInt|null"
Height of the image in pixels, if known.</t>
      <t>orientation: "UnsignedInt|null"
EXIF orientation value (1-8) as defined in the EXIF
specification (CIPA DC-008).  If present, indicates how
the image should be rotated/flipped for display.</t>
      <t>date: "UTCDate|null"
Date the image or video was captured (from EXIF
DateTimeOriginal or equivalent), if present.</t>
      <t>gps: "ImageGPS|null"
GPS coordinates from EXIF, if present.  An ImageGPS
object has the following properties:
      <list style="symbols">
          <t>latitude: "Number" — Latitude in decimal degrees.</t>
          <t>longitude: "Number" — Longitude in decimal degrees.</t>
        </list></t>
      <t>duration: "Number|null"
Duration in seconds for video content, if known.  This
is a floating-point number to allow sub-second precision.</t>
      <t>comment: "String|null"
Embedded EXIF comment or description, if present.  This
is read-only — it reflects the metadata stored in the
blob content and is not a user-editable property.</t>
    </list></t>
</list></t>

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

<t>When this capability is present, each object in the Blob/upload
(<xref target="JMAP-BLOB"/>, Section 4) <spanx style="verb">create</spanx> map <bcp14>MAY</bcp14> include the following
additional 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.  This allows
servers to optimise pipelines where intermediate blobs are never
needed after the request completes.</t>
</list></t>

<t>When this capability is present, Blob/upload also gains the
following additional request properties:</t>

<t><list style="symbols">
  <t>update: "Id[Object]" (default: null)
A map of blobId to an empty object.  No properties may be
set on a blob; the purpose of update is to "touch" the blob,
refreshing its lifetime on the server.  The response includes
an <spanx style="verb">updated</spanx> map of blobId to an object which <bcp14>MAY</bcp14> contain an
<spanx style="verb">expires</spanx> property with the new expiry time.  If the blobId
does not exist, it <bcp14>MUST</bcp14> be reported in a <spanx style="verb">notUpdated</spanx> map
with a <spanx style="verb">notFound</spanx> SetError.</t>
  <t>destroy: "Id[]" (default: null)
An array of blobIds to destroy.  The server <bcp14>MUST</bcp14> reject
any blob that is still referenced by another object with a
<spanx style="verb">blobHasReference</spanx> SetError.  If the blobId does not exist, the
server <bcp14>MUST</bcp14> return a <spanx style="verb">notFound</spanx> SetError.  Successfully
destroyed blobIds are returned in a <spanx style="verb">destroyed</spanx> array.
Failed destroys are returned in a <spanx style="verb">notDestroyed</spanx> map of
blobId to SetError.</t>
</list></t>

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

<t>When this capability is present, the Blob/upload response
(<xref target="JMAP-BLOB"/>, Section 4) and the Blob/convert response defined
below include an additional property.</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, the server does not have a
specific expiry time for the blob.</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>extract: ExtractRecipe</t>
  <t>compress: CompressRecipe</t>
  <t>decompress: DecompressRecipe</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
response also includes an <spanx style="verb">expires</spanx> property (see "The expires
response property" above).</t>

<t>If the conversion completed but encountered problems (e.g., a
corrupt archive where some entries extracted successfully but
others did not, or a truncated compressed stream that partially
decompressed), the response for that creation also includes:</t>

<t><list style="symbols">
  <t>isIncomplete: "Boolean" (default: false)
If true, the conversion did not complete cleanly.  The output
blob may be partial or missing some content.</t>
  <t>description: "String|null"
A human-readable description of the problem, if any.</t>
</list></t>

<t>If the conversion failed entirely and no usable output could be
produced, the server <bcp14>MUST</bcp14> return a <spanx style="verb">conversionFailed</spanx> SetError
in the <spanx style="verb">notCreated</spanx> map.</t>

<t>Creation id backreferences (using the <spanx style="verb">#</spanx> prefix) resolve to
the <spanx style="verb">id</spanx> of the created blob 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">supportedImageWriteTypes</spanx> capability.  The source image <bcp14>MUST</bcp14>
be in a format listed in <spanx style="verb">supportedImageReadTypes</spanx>.</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">supportedImageWriteTypes</spanx>, or the source blob is not in a format
listed in <spanx style="verb">supportedImageReadTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>, or the
requested dimensions exceed <spanx style="verb">maxImageDimension</spanx>.</t>
  <t>"conversionFailed" — the image conversion failed entirely.</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>
  <t>"conversionFailed" — the archive creation failed entirely.</t>
</list></t>

</section>
<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 ExtractRecipe
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 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="extractrecipe"><name>ExtractRecipe</name>

<t>An ExtractRecipe 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 ExtractRecipe 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">supportedExtractTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the extraction failed entirely.</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">supportedCompressTypes</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">supportedCompressTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the compression failed entirely.</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="decompressrecipe"><name>DecompressRecipe</name>

<t>A DecompressRecipe 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">supportedDecompressTypes</spanx>.</t>
  <t>"tooLarge" — the source blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the decompression failed entirely.</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">supportedDeltaTypes</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">supportedDeltaTypes</spanx>.</t>
  <t>"tooLarge" — a referenced blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the delta computation failed entirely.</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>"unknownFormat" — the delta blob is not valid for the specified
format (e.g., corrupt or malformed delta data).</t>
  <t>"invalidProperties" — the deltaType is not in <spanx style="verb">supportedPatchTypes</spanx>.</t>
  <t>"tooLarge" — a referenced blob exceeds <spanx style="verb">maxConvertSize</spanx>.</t>
  <t>"conversionFailed" — the patch application failed entirely.</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,
      "decompress": {
        "blobId": "Bd81c7f",
        "type": "application/gzip"
      }
    },
    "u2": {
      "extract": {
        "blobId": "#u1",
        "type": "application/x-tar"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The response for the ExtractRecipe 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 anchor="computing-and-applying-a-delta"><name>Computing and Applying a Delta</name>

<t>This example computes a unified diff between two versions of a
text file:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "d1": {
      "delta": {
        "blobId": "BoldVersion",
        "newBlobId": "BnewVersion",
        "type": "text/x-diff"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The response contains the delta blob:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "d1": {
      "id": "Bdelta789",
      "type": "text/x-diff",
      "size": 1234
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

<t>The delta can later be applied to the original blob to reconstruct
the new version:</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "create": {
    "p1": {
      "patch": {
        "blobId": "BoldVersion",
        "deltaBlobId": "Bdelta789",
        "deltaType": "text/x-diff"
      }
    }
  }
}, "0"]]
]]></sourcecode></figure>

<t>The result is a blob identical to "BnewVersion":</t>

<figure><sourcecode type="json"><![CDATA[
[["Blob/convert", {
  "accountId": "abc",
  "created": {
    "p1": {
      "id": "Breconstructed",
      "type": "application/octet-stream",
      "size": 48576
    }
  },
  "notCreated": {}
}, "0"]]
]]></sourcecode></figure>

</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
ExtractRecipe 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 anchor="blobhasreference"><name>blobHasReference</name>

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

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Description: The blob cannot be destroyed because it is still
referenced by one or more objects.  The client can use Blob/lookup
(<xref target="JMAP-BLOB"/>, Section 5) to discover which objects reference
the blob.</t>

<t>Reference: this document</t>

</section>
<section anchor="conversionfailed"><name>conversionFailed</name>

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

<t>Intended use: common</t>

<t>Change Controller: IETF</t>

<t>Description: The server was unable to perform the requested blob
conversion.</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-ietf-jmap-blobext-00</strong></t>

<t><list style="symbols">
  <t>No changes, just uploading with the new name</t>
</list></t>

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

<t><list style="symbols">
  <t>Removed resumableUploadUrl capability property.</t>
  <t>Added isIncomplete and description response properties for
partial conversion results.</t>
  <t>Added conversionFailed error code for total conversion failure.</t>
  <t>Made expires always present (null if indeterminate) rather than
optional.</t>
  <t>Split supportedImageTypes into supportedImageReadTypes and
supportedImageWriteTypes.</t>
  <t>Made all supported type lists nullable (null = not supported).</t>
  <t>Changed imageData duration from UnsignedInt to Number for
sub-second precision.</t>
  <t>Clarified imageData comment as read-only.</t>
  <t>Added EXIF orientation reference and digest algorithm registry
reference.</t>
  <t>Fixed grammar and consistent error ordering across recipes.</t>
  <t>Structural reorder: DataSourceObject before Blob/get, ArchiveEntry
promoted to peer section.</t>
</list></t>

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

<t><list style="symbols">
  <t>Added imageData property to Blob/get for image/video metadata
extraction (dimensions, orientation, date, GPS, duration).</t>
  <t>Renamed UnArchiveRecipe to ExtractRecipe and UnCompressRecipe
to DecompressRecipe.</t>
  <t>Split capability lists into separate create/extract pairs:
supportedArchiveTypes/supportedExtractTypes,
supportedCompressTypes/supportedDecompressTypes,
supportedDeltaTypes/supportedPatchTypes.</t>
</list></t>

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

<t><list style="symbols">
  <t>Moved noPersist from top-level Blob/upload property to per-item
in the create map, for consistency with Blob/convert.</t>
</list></t>

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

<t><list style="symbols">
  <t>Added update (touch) and destroy operations to Blob/upload.</t>
</list></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="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="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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
/bqyAAA=

-->

</rfc>

