<?xml version='1.0' encoding='UTF-8'?>
<rfc version="3" docName="draft-li-kvcache-efficient-transmission-00" category="std" consensus="true" submissionType="IETF" ipr="trust200902" tocInclude="true" tocDepth="3" sortRefs="true" symRefs="true" xml:lang="en">

  <front>
    <title abbrev="KV Cache Streaming over MOQT">Layer-Aligned Key-Value (KV) Cache Streaming over Media over QUIC Transport (MOQT)</title>
    <seriesInfo name="Internet-Draft" value="draft-li-kvcache-efficient-transmission-00"/>

    <author fullname="Zhiqiang Li" initials="Z." surname="Li">
      <organization>China Mobile</organization>
      <address>
        <postal><city>Beijing</city><code>100053</code>
        <country>China</country></postal>
        <email>lizhiqiangyjy@chinamobile.com</email>
      </address>
    </author>
    <author fullname="Zongpeng Du" initials="Z." surname="Du">
      <organization>China Mobile</organization>
      <address>
        <postal><city>Beijing</city><code>100053</code>
        <country>China</country></postal>
        <email>duzongpeng@chinamobile.com</email>
      </address>
    </author>
    <author fullname="Junjie Wang" initials="J." surname="Wang">
      <organization>Centec</organization>
      <address>
        <postal><city>Shanghai</city><code>201203</code>
        <country>China</country></postal>
        <email>wangjj@centec.com</email>
      </address>
    </author>
    <author fullname="Wei Cheng" initials="W." surname="Cheng">
      <organization>Centec</organization>
      <address>
        <postal><city>Shanghai</city><code>201203</code>
        <country>China</country></postal>
        <email>chengw@centec.com</email>
      </address>
    </author>
    <author fullname="Ying Zhao" initials="Y." surname="Zhao">
      <organization>Centec</organization>
      <address>
        <postal><city>Shanghai</city><code>200000</code>
        <country>China</country></postal>
        <email>zhaoying@centec.com</email>
      </address>
    </author>
    <author fullname="Chunhao Zhao" initials="C." surname="Zhao">
      <organization>SAIA</organization>
      <address>
        <postal><city>Shanghai</city><code>200125</code>
        <country>China</country></postal>
        <email>chunhao.zhao@sh-aia.com</email>
      </address>
    </author>
    <author fullname="Xun Sun" initials="X." surname="Sun">
      <organization>Inesa</organization>
      <address>
        <postal><city>Shanghai</city><code>200030</code>
        <country>China</country></postal>
        <email>sunxun@inesa.com</email>
      </address>
    </author>

    <date year="2026" month="November" day="2"/>
    <area>Web and Internet Transport</area>
    <keyword>MOQT</keyword>
    <keyword>Media over QUIC</keyword>
    <keyword>KV cache</keyword>
    <keyword>relay caching</keyword>
    <keyword>publish/subscribe</keyword>
    <keyword>distributed inference</keyword>

    <abstract>
      <t>The key-value (KV) cache of a language model can be computed once
      and reused by many inference instances, possibly at many sites.  Media
      over QUIC Transport (MOQT) provides publish/subscribe delivery through
      relays that cache objects without understanding their content.  This
      document specifies KV Cache Streaming (KVCS), an application of MOQT
      for delivering KV caches.  KVCS maps the identity of a token prefix
      to a Track Namespace built from keyed identifiers that do not reveal
      the prompt, carries the key and value tensors (or a jointly encoded
      form) in separate Tracks, aligns each Group with one model layer and
      each Object with one block of tokens, and defines a self-describing
      object payload and a manifest track.  These choices let consumers
      start using early layers while later layers are still being
      produced, retrieve only the layers and token blocks they need, and
      verify what they receive.</t>
    </abstract>
  </front>

  <middle>

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

      <section anchor="motivation">
        <name>Motivation</name>
        <t>Inference systems increasingly treat the KV cache as state that
        is decoupled from the engine that computed it: a prefill instance or
        cache server produces it, and decode instances, other replicas, or
        other sites consume it.  The same prefix (for example a long system
        prompt or a shared document) is often needed by many consumers.
        Point-to-point transfer from the producer to each consumer wastes
        backbone capacity and loads the producer.</t>
        <t>MOQT <xref target="I-D.ietf-moq-transport"/> already solves the
        analogous problem for media: an original publisher sends objects
        once to a relay tree, relays cache them, and many subscribers
        receive them with per-object priorities, without the relays
        understanding the payload.  A KV cache has a natural hierarchy that
        fits the MOQT object model: a cache belongs to a prefix, consists of
        key and value tensors, is computed layer by layer, and is divided
        into blocks of tokens.</t>
      </section>

      <section anchor="summary">
        <name>Summary of the Profile</name>
        <figure anchor="fig-model">
          <name>Mapping of a KV Cache to the MOQT Object Model</name>
          <artwork type="ascii-art">
Track Namespace  ("kvcs-1", scope_id, compat_id, anchor_key, pub_id)
 |
 +-- Track "manifest"        Group m: manifest version m
 |
 +-- Track "k.raw.s0"        key tensors, codec "raw", segment 0
 |    +-- Group 0            layer 0
 |    |    +-- Object 0      tokens of block 0, layer 0
 |    |    +-- Object 1      tokens of block 1, layer 0
 |    |    +-- ...
 |    +-- Group 1            layer 1
 |    +-- ...
 |    +-- Group L-1          layer L-1
 |
 +-- Track "v.raw.s0"        value tensors, same structure
 +-- Track "kv.&lt;codec&gt;.s0"   jointly encoded K and V (optional)
 +-- Track "k.raw.s1" ...    segment 1 (appended tokens)
</artwork>
        </figure>
        <t>The design choices are:</t>
        <ul>
          <li>Namespace from identity, not from text.  The namespace carries
          the keyed identifiers of the KV Cache Storage Protocol (KVSP)
          <xref target="I-D.li-kvcache-efficient-storage"/>, so relays and
          observers learn neither the model name nor the prompt, and two
          different prompts share a namespace only with negligible
          probability (<xref target="namespace"/>).</li>
          <li>Component tracks.  Key, value, and jointly encoded tensors are
          separate tracks, so a consumer can subscribe to what it needs and a
          publisher can offer several encodings (<xref target="tracks"/>).</li>
          <li>Layer-aligned groups.  A Group is one layer.  Production
          proceeds layer by layer, so Group IDs increase over time as MOQT
          expects, and a consumer can compute layer l while layer l+1 is
          still arriving (<xref target="groups"/>).</li>
          <li>Block objects.  An Object is the tensor of one token block in
          one layer, the smallest unit that is cached by relays and that can
          be selected with object filters (<xref target="objects"/>).</li>
          <li>Self-describing payloads.  Every Object carries its own
          descriptor and digest, so a subscriber that joins mid-track can use
          every Object it receives (<xref target="payload"/>).</li>
        </ul>
      </section>

      <section anchor="related">
        <name>Relationship to Other Work</name>
        <t><xref target="I-D.shi-moq-kvcache"/> also describes KV cache
        transmission over MOQT.  The present document differs in several
        respects that affect interoperability and security: (1) it does not
        place the model name or prompt in the namespace but keyed
        identifiers, which avoids disclosure and keeps different prompts in
        different tracks; (2) it aligns Groups with layers rather than with
        token chunks, so that consumers can pipeline computation across
        layers and Group IDs increase with production time; (3) it separates
        key, value, and jointly encoded tensors into tracks and identifies
        codecs through a registry instead of fixed compression levels; and
        (4) it defines the object payload, a manifest, integrity checks, and
        retrieval procedures for both live and completed caches.</t>
        <t>KVCS depends on KVSP for the Compatibility ID, Scope ID, Block
        Keys, and the codec registry.  Object payload protection uses
        <xref target="I-D.ietf-moq-secure-objects"/> when relays are not
        trusted with KV cache contents.</t>
      </section>
    </section>

    <section anchor="conventions">
      <name>Conventions and Definitions</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>
      <t>This document uses the MOQT terms Original Publisher, Relay, End
      Subscriber, Track, Track Namespace, Track Name, Group, Subgroup,
      Object, Location, Largest Object, Object Status, and Track Property
      as defined in <xref target="I-D.ietf-moq-transport"/>, and the KVSP
      terms Compatibility ID, Scope ID, Block Key, Block, and codec as
      defined in <xref target="I-D.li-kvcache-efficient-storage"/>.  In
      addition:</t>
      <dl newline="false">
        <dt>Anchor Key:</dt>
        <dd>The Block Key of the last complete block of segment 0, which
        identifies the token prefix of the publication.</dd>
        <dt>Publication:</dt>
        <dd>One production of the KV cache of a prefix by one Original
        Publisher, identified by a Publication ID.</dd>
        <dt>Segment:</dt>
        <dd>A contiguous range of complete blocks of the context.  Segment 0
        covers the prefix identified by the Anchor Key; later segments
        cover appended tokens.</dd>
        <dt>Component:</dt>
        <dd>The tensor kind carried by a track: "k" (keys), "v" (values), or
        "kv" (keys and values jointly encoded).</dd>
      </dl>
    </section>

    <section anchor="mapping">
      <name>Object Model Mapping</name>

      <section anchor="namespace">
        <name>Track Namespace</name>
        <t>A KVCS Track Namespace consists of exactly five Track Namespace
        Fields:</t>
        <table anchor="tbl-ns">
          <name>KVCS Track Namespace Fields</name>
          <thead>
            <tr><th>Field</th><th>Length</th><th>Content</th></tr>
          </thead>
          <tbody>
            <tr><td>0</td><td>6</td><td>ASCII "kvcs-1"</td></tr>
            <tr><td>1</td><td>16</td><td>Scope ID</td></tr>
            <tr><td>2</td><td>32</td><td>Compatibility ID</td></tr>
            <tr><td>3</td><td>32</td><td>Anchor Key</td></tr>
            <tr><td>4</td><td>16</td><td>Publication ID</td></tr>
          </tbody>
        </table>
        <t>Fields 1 to 4 are raw octets, not their hexadecimal encodings.
        The Publication ID is chosen at random by the Original Publisher for
        each production of the cache.</t>
        <t>Fields 0 to 3 identify content: any consumer that knows the token
        prefix, the scope key, and the Compatibility Descriptor can compute
        them.  Field 4 is needed because MOQT requires that an Object have
        identical bytes regardless of where it is retrieved
        (<xref target="I-D.ietf-moq-transport" section="2.1"/>), while two
        independent computations of the same prefix are not guaranteed to be
        bit-identical on all hardware.  A consumer that knows fields 0 to 3
        discovers the available publications through namespace prefix
        subscription (<xref target="discovery"/>).</t>
        <t>Namespace prefix matching gives useful aggregation points: the
        prefix ("kvcs-1", Scope ID) covers all publications of a scope and is
        the natural unit of authorization; the prefix
        ("kvcs-1", Scope ID, Compatibility ID, Anchor Key) covers all
        publications of one token prefix.</t>
      </section>

      <section anchor="tracks">
        <name>Track Names</name>
        <t>Track Names are ASCII strings with the following syntax, in
        ABNF <xref target="RFC5234"/>:</t>
        <sourcecode type="abnf">
track-name = "manifest" / "manifest.cose" / data-track
data-track = component "." codec-name "." "s" segment
component  = "k" / "v" / "kv"
codec-name = 1*32( %x61-7A / DIGIT / "-" )   ; KVSP codec name
segment    = "0" / ( %x31-39 *DIGIT )        ; no leading zeros
</sourcecode>
        <t>codec-name is the Name of a codec in the "KVSP Codecs" registry
        <xref target="I-D.li-kvcache-efficient-storage"/>.  For example,
        "k.raw.s0" carries the uncompressed key tensors of segment 0.  A
        publisher <bcp14>MAY</bcp14> offer the same segment in several encodings, for
        example "k.raw.s0" and "v.raw.s0" together with a "kv" track using a
        registered compressing codec; each data track is complete on its
        own.  A consumer
        selects either the pair of "k" and "v" tracks of one codec or one
        "kv" track.</t>
      </section>

      <section anchor="groups">
        <name>Groups</name>
        <t>The Group ID of a data track is the layer index, from 0 to L-1,
        where L is the number of layers in the Compatibility Descriptor.  The
        Original Publisher <bcp14>MUST</bcp14> publish the Objects of Group g before those
        of Group g+1 in the same track.  Producers that compute the cache in
        several passes over the token sequence (for example chunked prefill,
        where each chunk passes through all layers) <bcp14>MUST</bcp14> publish each pass as
        a separate segment, so that Group IDs within every track increase
        with time as recommended by <xref target="I-D.ietf-moq-transport" section="2.3.1"/>.</t>
        <t>The Objects of a Group are independently usable: each carries the
        tensor of one block for that layer.  A Group is a natural join point
        because a consumer needs every block of a layer before computing
        attention for that layer.</t>
        <t>The Original Publisher sends all Objects of a Group in a single
        Subgroup with Subgroup ID 0, in ascending Object ID order.  After the
        last Object of Group g it sends an Object with status End of Group.
        After the last Group of a track it sends an Object with status End of
        Track.</t>
      </section>

      <section anchor="objects">
        <name>Objects</name>
        <t>The Object ID is the index of the block within the segment,
        starting at 0.  The absolute block index is the first block index of
        the segment, given in the manifest, plus the Object ID.  Each Object
        carries one KVCS payload (<xref target="payload"/>).  Objects are
        never modified; a publisher that discovers an error in a publication
        stops it and starts a new publication with a new Publication ID.</t>
        <t>The Original Publisher <bcp14>SHOULD</bcp14> set the Publisher Priority of the
        Objects in Group g to floor(128 * g / L), so that, under contention,
        earlier layers, which a consumer needs first, are sent first.  The
        manifest track uses Publisher Priority 0.</t>
      </section>

      <section anchor="payload">
        <name>Object Payload</name>
        <figure anchor="fig-payload">
          <name>KVCS Object Payload</name>
          <artwork type="ascii-art">
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                  Magic ("KVO1" = 0x4B564F31)                  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    Version    |   Component   |             Flags             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             Layer                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Block Index                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                     Token Start (64 bits)                     |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Token Count                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             Codec             |           Reserved            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Data Length                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                  Data Digest (SHA-256, 32 octets)             |
|                              ...                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Data (variable)                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork>
        </figure>
        <dl newline="false">
          <dt>Magic:</dt><dd>0x4B564F31.</dd>
          <dt>Version:</dt><dd>1.</dd>
          <dt>Component:</dt><dd>1 for "k", 2 for "v", 3 for "kv".</dd>
          <dt>Flags:</dt><dd>Reserved; set to zero and ignored on receipt.</dd>
          <dt>Layer:</dt><dd>The layer index; equal to the Group ID.</dd>
          <dt>Block Index:</dt><dd>The index of the block within the segment;
          equal to the Object ID.</dd>
          <dt>Token Start:</dt><dd>The absolute position in the context of the
          first token of the block.</dd>
          <dt>Token Count:</dt><dd>The number of tokens; equal to the block
          size of the Compatibility Descriptor.</dd>
          <dt>Codec:</dt><dd>A value from the KVSP Codecs registry.</dd>
          <dt>Data Length:</dt><dd>The length of Data in octets.</dd>
          <dt>Data Digest:</dt><dd>SHA-256 <xref target="RFC6234"/> of
          Data.</dd>
          <dt>Data:</dt><dd>The tensor of the block for this layer.  For codec
          "raw" and component "k" or "v", this is the K or V section of the
          KVSP container for one layer; for component "kv" the K section is
          followed by the V section.</dd>
        </dl>
        <t>For codec "raw", the SHA-256 of the Data of a "k" Object followed by
        the Data of the "v" Object at the same Location, or the Data Digest of
        the corresponding "kv" Object, equals the KVSP layer digest of that
        block and layer, so that the two documents protect the same
        content.</t>
        <t>The header is 68 octets.  An End Subscriber <bcp14>MUST</bcp14> verify that Magic
        and Version are as specified, that Layer equals the Group ID, that
        Block Index equals the Object ID, that the header and Data Length
        account for the whole payload, and that the Data Digest matches.  An
        Object that fails any check <bcp14>MUST</bcp14> be discarded and treated as
        missing.</t>
      </section>

      <section anchor="manifest">
        <name>Manifest Track</name>
        <t>The manifest track describes the publication.  Each version of the
        manifest is Object 0 of a new Group, with Group IDs increasing by one
        per version.  A publication has exactly one manifest track: "manifest",
        whose payload is a JSON <xref target="RFC8259"/> object, or
        "manifest.cose", whose payload is a COSE_Sign1 structure
        <xref target="RFC9052"/> with that JSON object as its payload.  The
        JSON object is:</t>
        <sourcecode type="json">
{
  "kvcs": 1,
  "compat": { ...KVSP Compatibility Descriptor... },
  "layers": 32,
  "block_tokens": 16,
  "deterministic": false,
  "segments": [
    { "segment": 0, "first_block": 0, "blocks": 64,
      "block_keys_sha256": "&lt;hex32&gt;",
      "tracks": ["k.raw.s0", "v.raw.s0"],
      "complete": true },
    { "segment": 1, "first_block": 64, "blocks": 3,
      "block_keys_sha256": "&lt;hex32&gt;",
      "tracks": ["k.raw.s1", "v.raw.s1"],
      "complete": false }
  ]
}
</sourcecode>
        <t>"block_keys_sha256" is the SHA-256 of the concatenated raw Block
        Keys of the segment, which lets a consumer that has computed the keys
        confirm that the segment covers its tokens.  A segment entry <bcp14>SHOULD</bcp14>
        also carry "object_digests": for each data track, an array with one
        element per completed Group, in Group order, each element being the
        array of the hex Data Digests of the Group's Objects in Object order.
        During production, the publisher <bcp14>SHOULD</bcp14> publish a new manifest version
        at least every eight completed layers, so that a consumer can verify
        layers while later ones are still produced.  Because every Object has
        its own listed digest, consumers can also verify partial retrievals
        (a range of layers or of blocks).</t>
        <t>With "manifest.cose", the publisher signs each version with its
        producer key, using the COSE algorithm ES256 or EdDSA
        <xref target="RFC9053"/>, and places the key identifier in the "kid"
        header parameter.  Producer keys are distributed to the members of the
        scope together with the scope key, by means outside this document.
        "deterministic" is true
        only if the publisher guarantees that any publication of the same
        content fields produces bit-identical Objects.  A new manifest
        version is published whenever a segment is added or becomes
        complete.  The manifest <bcp14>MUST</bcp14> be consistent with the Compatibility ID
        in the namespace: a consumer <bcp14>MUST</bcp14> compute the Compatibility ID of
        "compat" and discard the publication if it differs.</t>
      </section>
    </section>

    <section anchor="publisher">
      <name>Publisher Behavior</name>
      <ul>
        <li>The Original Publisher <bcp14>MUST</bcp14> announce the full five-field namespace
        of each publication with PUBLISH_NAMESPACE, carrying the
        authorization the relay requires, so that relays can answer
        namespace subscriptions for any of its prefixes.</li>
        <li>It publishes the manifest before or together with the first data
        Object.</li>
        <li>It <bcp14>MUST NOT</bcp14> set OBJECT_DELIVERY_TIMEOUT or SUBGROUP_DELIVERY_TIMEOUT
        on data tracks: a KV cache with missing objects cannot be used, so
        timeouts only waste capacity.  It <bcp14>SHOULD</bcp14> set the Track Property
        MAX_CACHE_DURATION to the retention allowed for the scope.</li>
        <li>During live production it publishes each Object as soon as the
        layer of the block is computed, in the order of
        <xref target="groups"/>.</li>
        <li>It <bcp14>MUST NOT</bcp14> publish two different payloads at the same Location.
        Combined with the Publication ID, this keeps every Object immutable
        as MOQT requires.</li>
      </ul>
    </section>

    <section anchor="consumer">
      <name>Consumer Procedures</name>

      <section anchor="discovery">
        <name>Discovering Publications</name>
        <t>A consumer computes the Compatibility ID, Scope ID, and Block Keys
        of its prompt with KVSP.  For the longest prefix it wants to reuse,
        it uses the Block Key of that prefix's last block as the Anchor Key
        and sends SUBSCRIBE_NAMESPACE for the prefix ("kvcs-1", Scope ID,
        Compatibility ID, Anchor Key).  Each NAMESPACE response identifies
        one publication.  Alternatively, a KVSP Index Service lookup can
        return replica records whose holder URI is an MOQT URI identifying
        the full namespace.  If no publication exists for the full prefix,
        the consumer can try shorter prefixes, because the Anchor Key of a
        shorter prefix is an earlier Block Key in the same chain.  A
        publication whose prefix is longer than the consumer's needs
        cannot be found this way, because the consumer cannot compute its
        Anchor Key; the consumer finds such publications through a KVSP Index
        Service lookup of its own Block Keys, whose replica records name the
        publication.</t>
      </section>

      <section anchor="live">
        <name>Retrieval during Production</name>
        <t>To receive a cache that is still being produced, and to receive
        every Object exactly once, the consumer subscribes to each needed
        data track with:</t>
        <ul>
          <li>a LOCATION_FILTER of type Next Object (0x05); and</li>
          <li>a FILL_PARAMETERS parameter containing a LOCATION_FILTER of
          type Absolute Start (0x02) with StartGroup 0 and StartObject 0,
          which retrieves everything published before the subscription on a
          fill fetch stream.</li>
        </ul>
        <t>This combination is the exactly-once pattern described in
        <xref target="I-D.ietf-moq-transport" section="3.4"/>.  The consumer
        also subscribes to the manifest track: first to "manifest.cose", and,
        only if the publisher reports that this track does not exist and the
        consumer does not require producer authenticity, to "manifest".  It
        uses a LOCATION_FILTER of type
        Next Object (0x05) and a FILL_PARAMETERS parameter containing a
        LOCATION_FILTER of type Relative Start (0x01) with StartGroup 1, which
        delivers the current manifest on the fill fetch stream and later
        versions on the subscription.  A data track is complete for the
        consumer when it has received End of Track, or PUBLISH_DONE
        indicating that the track ended, or when the fill fetch stream has
        ended with a FIN and every Group listed in a manifest that marks the
        segment complete has been received.  Object Status values are not
        carried on fetch streams, so the last condition is the one that
        applies to a consumer that subscribes after production has
        finished.</t>
      </section>

      <section anchor="fetch">
        <name>Retrieval of Completed Caches</name>
        <t>To retrieve layers a through b of a completed segment, the
        consumer sends FETCH for each needed data track with a LOCATION_FILTER
        of type Absolute Start, Group End (0x03) with StartGroup a,
        StartObject 0, and EndGroupDelta b-a, and with GROUP_ORDER Ascending.
        The publisher or relay delivers Groups in ascending order, so the
        consumer can start computing layer a while later layers arrive.</t>
        <t>A consumer that needs only the first n blocks of a segment, because
        its prompt diverges after them, adds an OBJECTID_FILTER with the range
        0 to n-1 when the peer's MAX_FILTER_RANGES setup option is non-zero;
        otherwise it discards the excess Objects.</t>
      </section>

      <section anchor="verify">
        <name>Verification and Recovery</name>
        <t>The consumer verifies every Object as described in
        <xref target="payload"/> and every manifest as described in
        <xref target="manifest"/>.  A layer is usable when all Objects that
        the consumer needs in the corresponding Group, in all selected
        tracks, have been received and verified.  The consumer <bcp14>MUST NOT</bcp14>
        combine Objects of different publications in one segment unless the
        manifests of both publications state "deterministic": true.</t>
        <t>If Objects are missing (for example, reported as an unknown range
        in a fetch stream, or the stream is reset), the consumer retries with
        another relay or publication, retrieves the blocks with KVSP over
        HTTP, or recomputes the affected tokens.  It does not wait
        indefinitely: it <bcp14>SHOULD</bcp14> bound recovery by the time that recomputation
        would take.</t>
      </section>
    </section>

    <section anchor="relays">
      <name>Relay Considerations</name>
      <t>KVCS requires no relay functions beyond those of MOQT.  Relays cache
      KVCS Objects by Full Track Name and Location like any other Objects
      and fill gaps with upstream fetches.  Because each Object is
      immutable and the namespace binds it to a single publication, a relay
      can serve the same Objects to every authorized subscriber of the
      prefix.  Relays <bcp14>MUST</bcp14> enforce authorization at least at the granularity
      of the namespace prefix ("kvcs-1", Scope ID), so that subscribers
      cannot obtain caches of a scope they are not authorized for.  Relays
      honor MAX_CACHE_DURATION.</t>
      <t><xref target="fig-flow"/> shows an example in which a consumer
      attached to Relay B receives a cache that has partly been cached at
      Relay B and is partly still being produced.</t>
      <figure anchor="fig-flow">
        <name>Example Delivery through Two Relays</name>
        <artwork type="ascii-art">
Producer          Relay A           Relay B           Consumer
   |  PUBLISH_NAMESPACE  |                |                 |
   |  (5-field ns)       |                |                 |
   |--------------------&gt;|---------------&gt;|                 |
   |                     |                |  SUBSCRIBE      |
   |                     |                |  "k.raw.s0",    |
   |                     |                |  Next Object +  |
   |                     |                |  fill from 0/0  |
   |                     |                |&lt;----------------|
   |                     |  SUBSCRIBE     |                 |
   |                     |&lt;---------------|                 |
   |  SUBSCRIBE          |                |  fill stream:   |
   |&lt;--------------------|                |  groups 0..4    |
   |                     |                |  from cache     |
   |                     |                |----------------&gt;|
   | group 5 objects     |                |                 |
   |--------------------&gt;| group 5        | group 5         |
   |                     |---------------&gt;|----------------&gt;|
   | group 6 ...         |                |                 |
   | End of Track        |---------------&gt;|----------------&gt;|
</artwork>
      </figure>
    </section>

    <section anchor="ops">
      <name>Operational Considerations</name>
      <ul>
        <li>Object size.  An Object holds Token Count x kv_heads x head_dim
        elements; with 16 tokens, 8 heads, 128 dimensions, and two octets per
        element, a "k" Object carries 32 KiB.  Block sizes that give Objects
        between 16 KiB and 1 MiB balance per-object overhead against
        granularity.</li>
        <li>Streams.  Each Group of each subscribed track uses one Subgroup
        stream, so a consumer of two tracks of an 80-layer model can see 160
        streams per segment.  Endpoints <bcp14>SHOULD</bcp14> grant enough concurrent
        unidirectional streams for the number of layers they pipeline.</li>
        <li>Retention.  Publishers <bcp14>SHOULD</bcp14> align MAX_CACHE_DURATION with the
        retention of the corresponding KVSP replicas.</li>
        <li>Fallback.  Consumers <bcp14>SHOULD</bcp14> be able to fall back to HTTP retrieval
        through KVSP when no MOQT path is available.</li>
      </ul>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>
      <t>The security considerations of <xref target="I-D.ietf-moq-transport"/>
      and of <xref target="I-D.li-kvcache-efficient-storage"/> apply.</t>
      <t>Confidentiality.  MOQT relays can read Object payloads.  KV caches
      reveal information about the prompts from which they were computed.
      When relays are not trusted with the contents of a scope, publishers
      <bcp14>MUST</bcp14> protect Object payloads end to end with
      <xref target="I-D.ietf-moq-secure-objects"/>, using keys distributed to
      the authorized members of the scope.</t>
      <t>Integrity.  The Data Digest detects accidental corruption.  A relay
      that is not trusted could replace both data and digest; protection
      against such a relay requires the authenticated encryption of secure
      objects.  Consumers <bcp14>MUST NOT</bcp14> rely on the Data Digest alone when relays
      are not trusted.  Secure objects authenticate membership of the
      scope, not the identity of the producer: any member of the scope could
      publish a poisoned cache.  When producer authenticity matters,
      publishers <bcp14>MUST</bcp14> use the "manifest.cose" track with "object_digests"
      (<xref target="manifest"/>), and consumers <bcp14>MUST</bcp14> verify the signature,
      and the Data Digest of every Object against the signed list, before
      using the Object.</t>
      <t>Authorization.  Relays <bcp14>MUST</bcp14> authorize PUBLISH_NAMESPACE,
      SUBSCRIBE_NAMESPACE, SUBSCRIBE, and FETCH for KVCS namespaces by scope.
      A publisher that is not authorized for a scope could otherwise publish
      poisoned caches under the scope's identifiers.</t>
      <t>Resource use.  A consumer can request many layers and tracks.  Relays
      apply the resource protections of MOQT, and publishers <bcp14>SHOULD</bcp14> limit the
      number of concurrent fetches per subscriber.</t>
    </section>

    <section anchor="privacy">
      <name>Privacy Considerations</name>
      <t>The namespace contains keyed identifiers that cannot be linked to a
      prompt without the scope key, and track names reveal only the
      component, codec, and segment number.  The number of Groups and
      Objects and their sizes still reveal the number of layers and the
      length of the context.  Deployments that consider this sensitive can
      pad segments to a fixed number of blocks.</t>
      <t>Anchor Keys are deterministic within a scope, so a relay can tell
      that two subscribers requested the same prefix, and a sequence of
      subscriptions for successively shorter prefixes (<xref target="discovery"/>)
      reveals where their prompts diverge from published ones.  Relays learn
      this only for scopes whose traffic they carry; deployments that do not
      trust relays with such linkage use KVSP lookups to find exact
      publications instead of probing prefixes.</t>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>IANA is requested to create a registry named "KVCS Components"
      within the "KV Cache Storage Protocol (KVSP)" registry group created
      by <xref target="I-D.li-kvcache-efficient-storage"/>.  Each entry has a
      name (lowercase ASCII), a numeric value (8 bits) used in the Component
      field, a description, and a reference.  The registration policy is
      Specification Required <xref target="RFC8126"/>.  Initial contents:</t>
      <table anchor="tbl-iana">
        <name>Initial KVCS Components</name>
        <thead>
          <tr><th>Name</th><th>Value</th><th>Description</th></tr>
        </thead>
        <tbody>
          <tr><td>(reserved)</td><td>0</td><td>Reserved</td></tr>
          <tr><td>k</td><td>1</td><td>Key tensors</td></tr>
          <tr><td>v</td><td>2</td><td>Value tensors</td></tr>
          <tr><td>kv</td><td>3</td><td>Key and value tensors jointly encoded</td></tr>
        </tbody>
      </table>
      <t>The names "manifest" and "manifest.cose" are reserved as Track Names
      and are not components.  This document makes no request of MOQT registries.</t>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/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"/>
    </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="2119"/>
  <seriesInfo name="DOI" value="10.17487/RFC2119"/>
</reference>
        <reference anchor="RFC5234" target="https://www.rfc-editor.org/info/rfc5234">
  <front>
    <title>Augmented BNF for Syntax Specifications: ABNF</title>
    <author fullname="D. Crocker" initials="D." role="editor" surname="Crocker"/>
    <author fullname="P. Overell" initials="P." surname="Overell"/>
    <date month="January" year="2008"/>
    </front>
  <seriesInfo name="STD" value="68"/>
  <seriesInfo name="RFC" value="5234"/>
  <seriesInfo name="DOI" value="10.17487/RFC5234"/>
</reference>
        <reference anchor="RFC6234" target="https://www.rfc-editor.org/info/rfc6234">
  <front>
    <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title>
    <author fullname="D. Eastlake 3rd" initials="D." surname="Eastlake 3rd"/>
    <author fullname="T. Hansen" initials="T." surname="Hansen"/>
    <date month="May" year="2011"/>
    </front>
  <seriesInfo name="RFC" value="6234"/>
  <seriesInfo name="DOI" value="10.17487/RFC6234"/>
</reference>
        <reference anchor="RFC8126" target="https://www.rfc-editor.org/info/rfc8126">
  <front>
    <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
    <author fullname="M. Cotton" initials="M." surname="Cotton"/>
    <author fullname="B. Leiba" initials="B." surname="Leiba"/>
    <author fullname="T. Narten" initials="T." surname="Narten"/>
    <date month="June" year="2017"/>
    </front>
  <seriesInfo name="BCP" value="26"/>
  <seriesInfo name="RFC" value="8126"/>
  <seriesInfo name="DOI" value="10.17487/RFC8126"/>
</reference>
        <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/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"/>
    </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="8174"/>
  <seriesInfo name="DOI" value="10.17487/RFC8174"/>
</reference>
        <reference anchor="RFC8259" target="https://www.rfc-editor.org/info/rfc8259">
  <front>
    <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
    <author fullname="T. Bray" initials="T." role="editor" surname="Bray"/>
    <date month="December" year="2017"/>
    </front>
  <seriesInfo name="STD" value="90"/>
  <seriesInfo name="RFC" value="8259"/>
  <seriesInfo name="DOI" value="10.17487/RFC8259"/>
</reference>
        <reference anchor="RFC9052" target="https://www.rfc-editor.org/info/rfc9052">
  <front>
    <title>CBOR Object Signing and Encryption (COSE): Structures and Process</title>
    <author fullname="J. Schaad" initials="J." surname="Schaad"/>
    <date month="August" year="2022"/>
    </front>
  <seriesInfo name="STD" value="96"/>
  <seriesInfo name="RFC" value="9052"/>
  <seriesInfo name="DOI" value="10.17487/RFC9052"/>
</reference>
        <reference anchor="RFC9053" target="https://www.rfc-editor.org/info/rfc9053">
  <front>
    <title>CBOR Object Signing and Encryption (COSE): Initial Algorithms</title>
    <author fullname="J. Schaad" initials="J." surname="Schaad"/>
    <date month="August" year="2022"/>
    </front>
  <seriesInfo name="RFC" value="9053"/>
  <seriesInfo name="DOI" value="10.17487/RFC9053"/>
</reference>
        <reference anchor="I-D.ietf-moq-transport" target="https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-22">
  <front>
    <title>Media over QUIC Transport</title>
    <author fullname="Suhas Nandakumar" initials="S." surname="Nandakumar">
      <organization>Cisco</organization>
    </author>
    <author fullname="Victor Vasiliev" initials="V." surname="Vasiliev">
      <organization>Google</organization>
    </author>
    <author fullname="Ian Swett" initials="I." surname="Swett">
      <organization>Google</organization>
    </author>
    <author fullname="Alan Frindell" initials="A." surname="Frindell">
      <organization>Meta</organization>
    </author>
    <date day="1" month="October" year="2026"/>
    </front>
  <seriesInfo name="Internet-Draft" value="draft-ietf-moq-transport-22"/>
</reference>
        <reference anchor="I-D.ietf-moq-secure-objects" target="https://datatracker.ietf.org/doc/html/draft-ietf-moq-secure-objects-01">
  <front>
    <title>End-to-End Secure Objects for Media over QUIC Transport</title>
    <author fullname="Cullen Fluffy Jennings" initials="C. F." surname="Jennings">
      <organization>Cisco</organization>
    </author>
    <author fullname="Suhas Nandakumar" initials="S." surname="Nandakumar">
      <organization>Cisco</organization>
    </author>
    <author fullname="Richard Barnes" initials="R." surname="Barnes">
      <organization>Cisco</organization>
    </author>
    <date day="6" month="July" year="2026"/>
    </front>
  <seriesInfo name="Internet-Draft" value="draft-ietf-moq-secure-objects-01"/>
</reference>
        <reference anchor="I-D.li-kvcache-efficient-storage" target="https://datatracker.ietf.org/doc/html/draft-li-kvcache-efficient-storage-00">
          <front>
            <title>Key-Value (KV) Cache Storage Protocol (KVSP): Indexing, Placement, Prefetch, and Migration for Distributed Inference</title>
            <author initials="Z." surname="Li" fullname="Zhiqiang Li"/>
            <author initials="Z." surname="Du" fullname="Zongpeng Du"/>
            <author initials="J." surname="Wang" fullname="Junjie Wang"/>
            <author initials="W." surname="Cheng" fullname="Wei Cheng"/>
            <author initials="Y." surname="Zhao" fullname="Ying Zhao"/>
            <author initials="C." surname="Zhao" fullname="Chunhao Zhao"/>
            <author initials="X." surname="Sun" fullname="Xun Sun"/>
            <date year="2026" month="November" day="2"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-li-kvcache-efficient-storage-00"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <reference anchor="I-D.shi-moq-kvcache" target="https://datatracker.ietf.org/doc/html/draft-shi-moq-kvcache-01">
  <front>
    <title>KVCache over MoQT</title>
    <author fullname="Hang Shi" initials="H." surname="Shi">
      <organization>Huawei Technologies</organization>
    </author>
    <author fullname="Shengnan Yue" initials="" surname="Yue">
      <organization>China Mobile</organization>
    </author>
    <date day="9" month="April" year="2025"/>
    </front>
  <seriesInfo name="Internet-Draft" value="draft-shi-moq-kvcache-01"/>
</reference>
      </references>
    </references>

    <section anchor="vectors" numbered="true">
      <name>Encoding Examples</name>
      <t>Using the values of the KVSP test vectors (Scope ID
      6d1c6481cd428737da312c089db3832a, Compatibility ID 5ed5c2f2...ee0f,
      Anchor Key 65327588...efc1) and Publication ID
      0123456789abcdef0123456789abcdef, the Track Namespace is encoded as
      follows (108 octets: a field count of 5, then each field prefixed by
      its length):</t>
      <artwork>
05 06 6b 76 63 73 2d 31 10 6d 1c 64 81 cd 42 87
37 da 31 2c 08 9d b3 83 2a 20 5e d5 c2 f2 38 83
96 55 d7 c4 02 9e 12 b7 f3 1c af 9e 74 21 f4 ed
b4 05 7f ee e6 da b7 60 ee 0f 20 65 32 75 88 4c
a4 4f 89 45 fd 4c 90 26 11 c4 67 39 4b 73 65 6e
64 c7 8d 85 22 64 8c b7 5a ef c1 10 01 23 45 67
89 ab cd ef 01 23 45 67 89 ab cd ef
</artwork>
      <t>The payload header of a "k" Object at Group 0, Object 1 (Token Start
      4, Token Count 4, codec "raw") is shown below.  For brevity the
      example uses 16 octets of Data with values 0x00 to 0x0f; with the
      geometry of the KVSP test vector, real Data would hold 4 x 8 x 128 x 2
      = 8192 octets.</t>
      <artwork>
4b 56 4f 31 01 01 00 00 00 00 00 00 00 00 00 01
00 00 00 00 00 00 00 04 00 00 00 04 00 01 00 00
00 00 00 10 be 45 cb 26 05 bf 36 be bd e6 84 84
1a 28 f0 fd 43 c6 98 50 a3 dc e5 fe db a6 99 28
ee 3a 89 91
</artwork>
    </section>

    <section anchor="acknowledgments" numbered="false">
      <name>Acknowledgments</name>
      <t>The authors thank the MOQ working group participants whose
      discussions of non-media uses of MOQT informed this document.</t>
    </section>
  </back>
</rfc>