Hash identity
One job: why an event's identity is computed, and what the computation excludes. The identity is the CBV 2.0 §8.9 standardized event hash — an ni:///sha-256 URI derived from the event's own canonicalized content, with GS1 Digital Link normalization, so the same fact written as a URN or as a Digital Link URI hashes to the same identity.
What §8.9 excludes, and why
By construction the algorithm excludes eventID, recordTime and errorDeclaration. The exclusions are the point:
- eventID — identity cannot depend on an assigned name, or two parties naming the same fact differently would make it two facts.
- recordTime — identity cannot depend on when a door heard about the fact, or the same event captured twice would be two events. That is what makes capture idempotent: a replay computes the same identity and is recognized, not duplicated.
- errorDeclaration — a correction points at the event it corrects; folding it into the hash would move the target as you declare against it.
The same event captured twice is the same event; a changed event is a different one.
Byte-matched to the reference
The suite is gated on the CBV 2.0 §8.9 reference vectors published by Ralph Troeger, co-chair of the EPCIS & CBV 2.0 MSWG, in RalphTro/epcis-event-hash-generator (MIT) — the reference implementation of the algorithm. The corpus is vendored under vendor/epcis-event-hash/ and sha256-pinned. Fetch the vector pair from its source, then run — executed 2026-07-31 against the published package:
$ V=https://raw.githubusercontent.com/RalphTro/epcis-event-hash-generator
$ curl -sSO $V/master/tests/examples/epcisDocWithSingleEvent.jsonld
$ curl -sSO $V/master/tests/examples/epcisDocWithSingleEvent.hashes
$ npx epcis.dev hash epcisDocWithSingleEvent.jsonld
hash 0 ni:///sha-256;ffa491b16867e34a7791a8d5389d826afc24e63a121026b6a4004ace38631b4b?ver=CBV2.0
$ cat epcisDocWithSingleEvent.hashes
ni:///sha-256;ffa491b16867e34a7791a8d5389d826afc24e63a121026b6a4004ace38631b4b?ver=CBV2.0
Byte-identical to the reference's published expected hash.
The same digest from every door
One algorithm, one identity, regardless of which door computes it — local verb and live door, executed 2026-07-31 on the shipping fixture from the in-tarball corpus:
$ CORPUS=node_modules/epcis.dev/golden-corpus
$ npx epcis.dev hash $CORPUS/valid-standard/object-event-shipping.json
hash 0 ni:///sha-256;e5624abcce4b2fc226743e8891f69c12a07ad508953749d9b9ede6771424f91e?ver=CBV2.0
$ curl -sS -X POST https://epcis.dev/hash \
-H 'content-type: application/json' \
--data-binary @$CORPUS/valid-standard/object-event-shipping.json
{
"algorithm": "CBV 2.0 §8.9 event hash",
"count": 1,
"hashes": [
"ni:///sha-256;e5624abcce4b2fc226743e8891f69c12a07ad508953749d9b9ede6771424f91e?ver=CBV2.0"
]
}
The canonicalization steps are exposed in the library barrel for anyone re-deriving the identity themselves:
import { eventHash, canonicalJson, preHashString } from "epcis.dev";