Skip to content
VERASPEC
Repository
VER 1.0.1 errata annexstable

§2 What changed in artifact release 1.0.1

2.1 Schema (ver-record.schema.json)

$id moves to https://verstandard.org/schemas/ver-record-1.0.1.json. A published $id is never reused or overwritten; the 1.0.0 schema stays retrievable and immutable at its own identifier. title becomes VER Record 1.0 (artifact release 1.0.1); the top-level description names this annex. ver_version remains const: "1.0".

There are exactly three constraint changes:

#LocationChangeBasis
1/properties/identity/properties/perceptual/itemsDigest length is bound to the algorithm: pdq/1.0^[a-f0-9]{64}$, phash-dct/64^[a-f0-9]{16}$, expressed as two if/then subschemas. The alg enum is unchanged.E22; SCH-07, App. D #1
2/properties/identity/properties/pixel_hash"additionalProperties": false added. The subschema's own "alg": true, "value": true entries — inert without it — now do the work they were written for.SCH-03
3/properties/identity/properties/content_hash{"$ref": "#/$defs/sha256Hash"} becomes {"allOf": [{"$ref": "#/$defs/sha256Hash"}], "unevaluatedProperties": false}.SCH-03, SCH-04

Changes 2 and 3 close the identity sub-objects that the published schema left open by omission: identity itself is closed, and the pixel_hash subschema's "alg": true, "value": true whitelist entries are proof that closure was intended there and forgotten. unevaluatedProperties is used for content_hash rather than additionalProperties because the constraint has to see through the $ref to know that alg and value were evaluated.

$defs/sha256Hash is deliberately not closed. Closing it would break the pixel_hash branch, which composes sha256Hash with width/height through allOf; the closure is therefore applied at each use site. Every other object in the schema is left exactly as published — including the seven objects the audit found accidentally open (spaceDescriptor.model, .reference, .provenance, metadata.trust[], conflicts[].values[], embedding.recipe, and sha256Hash itself). Closing those is a tightening with no corrective urgency; it is tracked for 1.1.

Effect on existing Records: a 1.0.0-valid Record fails the 1.0.1 schema only if it carries a perceptual digest of the wrong length for its declared algorithm, or an undeclared member inside identity.content_hash or identity.pixel_hash. In all three cases the Record already violated normative 1.0.0 prose (§5 for digest widths, §10 plus the schema's own closure policy for the identity object), so no conformant Record is invalidated. The frozen 1.0.0 example is itself one of the invalidated instances — see §2.2 and E26.

2.2 Example (example-record.json)

Five corrections, no other byte changed:

#Pointer1.0.01.0.1Annex item
a/identity/perceptual/0/value96 hex charactersf8f8f0cee0f4a84f06370a22038f63f0b36e2ed596621e1d33e6b39c4e9c9b22 (64 hex)E22, E26
b/metadata/raw/0/sha2565e884898…1542d8 (= SHA-256 of the ASCII string password)a106fd0f3203936b46f396bfcf79dcc396f5eda43508bb760c9649d50a5c6e7aE11, E26
c/metadata/normalized/@contexta bare XMP namespace URI that does not define dc:an inline context object defining dc and Iptc4xmpExtE26
d/provenance/chainfour events, one embedfive events, two embed (one per embedding)E16, E26
e/metadata/raw/0/bytesa 30-octet elision of a profile whose own header declares 3144 octets, with no ICC_PROFILE\0 prefixa complete 602-octet JPEG APP2 ICC payload: ICC_PROFILE\0 + the two sequence octets 01 01 + a complete 588-octet sRGB ICC profileE11, E26

On (a): the published 96-hex value is the intended 64-hex digest with its own first 32 characters appended verbatim — value[:32] == value[-32:] — so the corrected value is value[:64], recovered rather than invented.

On (e): the 1.0.0 payload was an elision, and an elision is not byte-exact preservation under E11 — so the example was non-conformant at its own declared conformance_level of L3, both against E11's JPEG row (which requires the ICC_PROFILE\0 identifier prefix and the sequence octets) and against E26's prohibition on shipping an elided segment at L1 or above. Rather than lower the example's conformance level, 1.0.1 ships a real segment. The payload is exactly what a JPEG APP2 ICC marker carries, minus the two-octet FFE2 marker and the two-octet length field:

  • octets 0–11: the ASCII identifier ICC_PROFILE followed by one NUL;
  • octets 12–13: the sequence octets 01 01 — chunk 1 of 1;
  • octets 14–601: a complete ICC profile, 588 octets, whose header's profile-size field reads 588, whose signature at offset 36 is acsp, whose device class is mntr, whose data colour space is RGB, and which lcms re-opens as an sRGB monitor profile.

The profile was produced once with PIL.ImageCms.createProfile("sRGB") (lcms2) and its 12-octet creation-date/time header field at offset 24 was zeroed so that the artifact is byte-reproducible rather than dependent on when it was generated. sha256 is the SHA-256 of the full 602 decoded octets, per E11.

Reproduce the payload and its digest from the repository root:

bash
.venv/bin/python - <<'PY'
import base64, hashlib, io
from PIL import ImageCms
p = bytearray(ImageCms.core.profile_tobytes(ImageCms.createProfile("sRGB")))
p[24:36] = b"\x00" * 12 # zero the creation date/time
p = bytes(p)
assert int.from_bytes(p[0:4], "big") == len(p) and p[36:40] == b"acsp"
ImageCms.getOpenProfile(io.BytesIO(p)) # parses as a real ICC profile
payload = b"ICC_PROFILE\x00" + b"\x01\x01" + p
print(len(payload), hashlib.sha256(payload).hexdigest())
print(base64.b64encode(payload).decode())
PY

Expected: 602 a106fd0f3203936b46f396bfcf79dcc396f5eda43508bb760c9649d50a5c6e7a.

Every other identifier in the example — model checkpoints, reference-set URIs, vector URIs, the content_hash and pixel_hash values — remains illustrative per E26. Edit (e) makes the one claim that a Record can make about its own contents self-consistent: the segment metadata.availability.icc reports as present is now genuinely preserved, byte-exact, per E11's JPEG row.

The corrected example validates under both the frozen 1.0.0 schema and the 1.0.1 schema. This is deliberate: the golden example must never be the artifact that forces a consumer upgrade. It also validates clean under the conformance profile validator at its declared L3, with the single expected VER308 warning (an L3 Record SHOULD carry a signature; this one does not, because a signature over illustrative data would itself be illustrative).