Code change:
4. <del> The "br-d" content encoding identifies a resource that is a </del> <ins> The "dcb" content encoding identifies a resource that is a </ins> "Dictionary-Compressed Brotli" stream. <del> A "Dictionary-Compressed Brotli" stream is a Brotli RFC7932 stream for a response that has been compressed with an external dictionary using a compression window not larger than 16 MB. </del> <ins> A "Dictionary-Compressed Brotli" stream has a fixed header that is followed by a Shared Brotli SHARED-BROTLI stream.  The header consists of a fixed 4 byte sequence and a 32 byte hash of the external dictionary that was used.  The Shared Brotli stream is created using the referenced external dictionary and a compression window that is at most 16 MB in size. The 36-byte fixed header is as follows: </ins> <del> Clients that announce support for br-d content encoding MUST be able </del> <ins> Clients that announce support for dcb content encoding MUST be able </ins> to decompress resources that were compressed with a window size of up to 16 MB.

Related discussion:
text: It would be more of a problem if we were trying to spec a universal solution, but if we scope this to just this content-encoding, then we're free to reserve whatever code points we want and attach whatever semantics we want.
Thanks. I guess the main question I have is if there would be benefits to Zstandard itself for the files to be self-contained with the identification of the dictionary that they were encoded with or the possibility of mismatching dictionaries on compression and decompression (or being able to find the matching dictionary given just the compressed file) are issues that are HTTP-specific. I'm fine with specifying that the encoded files carry the dictionary hash (before the compressed stream data) and having different ways for Zstandard and Brotli to do that actual embedding. That said, the tooling gets more complicated on the encode and decode side to generate the frame and insert it in the correct place in the compressed file and at decompression time, that makes the client more format-aware, having to parse more of the stream to extract the dictionary and then re-send the full stream through the decoder (at least until the decoder library becomes aware of embedded dictionary hash).
NAME Is this really what you want in this case? The decoder needs to know where to find the dictionary, so wouldn't you want this to be a breaking change to the format such that a decoder that has a dictionary is fine and a decoder that doesn't knows to go get one. ... And - importantly - an older decoder will abort. (I confess that I don't know what the zstd frame extension model is and didn't check.)
I don't think we're contemplating a model where Zstd can ingest a frame and figure out on its own where to find the dictionary it needs and then load it and use it. I expect that the enclosing application will parse this header, get the hash, and then find the dictionary and provide it to Zstd. The advantage to using the skippable frame is that then you can provide the whole input to Zstd (including existing versions) and it will work rather than have to pull the header off.
One thing I realized now - by assuming that the hash length is 32 bytes, we're assuming the hash would remain SHA-256 forever. That might be how things play out, but it that we'd need to change hashes at some point.