rubrapack Manual←↑→

37 Deterministic identities and reproducible packages

Windows Installer identifies things by GUIDs and keys that must be stable: the same component must keep the same ComponentId in every version, or repair and upgrade misbehave. Generating them from the content, instead of storing them by hand, keeps them stable and makes builds reproducible. This page describes rubrapack's rules; other rules work too as long as they are stable.

37.1 Name-based GUIDs (UUID version 8) [spec: RFC 9562]#

digest = SHA-256( u32le(len(tag)) || tag
                  || u32le(1)                                   (format version)
                  || for each field: u32le(len(field)) || field )  (fields in UTF-8)
uuid   = digest[0..16), then byte 6 = (byte 6 & 0x0F) | 0x80   (version 8)
                             byte 8 = (byte 8 & 0x3F) | 0x80   (variant 10)
text   = "{" + hex(bytes 0-3) "-" hex(4-5) "-" hex(6-7) "-" hex(8-9) "-" hex(10-15) + "}"
         upper case, bytes in order

Length prefixes keep ("ab","c") and ("a","bc") apart; the tag keeps different kinds of identity apart.

IdentityTagFields
ComponentIdrubrapack.componentupgrade code, scope (machine), component architecture, logical target path (<dir id>/<file name>), key path kind (file), key path name (the File key)
ProductCoderubrapack.productupgrade code, architecture, scope, the version's first three parts
package code (reproducible builds)rubrapack.packagehex SHA-256 of the package built with an all-zero package code

The ProductCode changes with the three-part version - which is what a major upgrade needs - and the ComponentIds do not.

37.2 Keys#

Table keys (File, Component, Directory) are identifiers: [A-Za-z_][A-Za-z0-9_.]*, at most 72 characters. rubrapack uses the author's IDs for files and folders as given and derives the rest:

key = prefix + "_" + first 20 lower-case hex digits of SHA-256(logical name)
      prefix C for components (logical name: the File key), D for intermediate folders
      (logical name: "<standard folder>/<part>/<part>..."), F for files from wildcards

37.3 Reproducible packages#

A package is byte-for-byte reproducible when nothing depends on the clock, the machine or the order of hash tables: fixed CFB directory times (zero), fixed cabinet dates, string ids assigned in byte order of the strings, rows sorted by key, streams in a fixed order, no random GUIDs. The one identity that must differ between package files is the package code; derive it from the content (as above) when reproducibility matters, and use a random one otherwise.