URS Canonicalization Specification v0.1.0
Deterministic normalization rules, content-addressing, and hash computation for the URS (Universal Representation System) data model β enabling verifiable identity, deterministic comparison, and stable content addressing across all URS codecs.Preamble
This document specifies the URS Canonicalization algorithms β the deterministic transformation rules that reduce any valid URS representation (URS Β§1βΒ§5) to a canonical byte sequence suitable for hashing, content-addressing, identity binding, and cross-implementation comparison.
URS Canonicalization is a companion specification to the URS Formal Specification (v0.1.0). It depends on URS but URS does not depend on it β the URS data model is complete without canonicalization, but all constitutional verification (identity binding, provenance hashing, attestation chains) requires canonical form.
Relationship to URS: The URS spec defines canonical representation rules (Β§4): identity levels, graph equivalence, ordering, normalization, cycle handling, and per-kind rules. This specification defines the algorithms that implement those rules deterministically. The rules are frozen with URS; the algorithms may be revised independently (separate versioning).
Constitutional dependencies: URS Β§4 (Canonical Representation Rules), CORE-LD Β§7 (Invariants I1βI23, incl. I21βI23 in Β§7.5), URS Β§6 (Provenance).
Codec independence: This canonicalization algorithm is codec-agnostic. It operates on the URS representation graph, not on any serialized form. Every conforming CORE-LD encoding binding (JSON-CORE-LD, CBOR-CORE-LD, and future bindings) SHALL reference this canonicalization specification for hash computation and identity binding.
Alignment (July 31, 2026): this specification has been aligned to the CORE-LD v0.1.0 family β the DAG-JSON-LD / DAG-CBOR-LD codec drafts are superseded by the JSON-CORE-LD and CBOR-CORE-LD encoding bindings (CORE-LD Β§6.2), and the codec registry (Β§5.1) and DAG addressing mode (Β§5.3) are updated accordingly. The canonicalization algorithms (Β§2βΒ§4) are unchanged by the alignment.
Status: Frozen-readiness β conformance suite verified (24 tests, test_urs_canonicalization.py, Β§8.5); formal freeze pending constitutional artifact compilation via UCF forge per the publishing directive.
Section 1: Canonical Form Definition
1.1 What Canonicalization Produces
URS Canonicalization transforms a URS representation graph into a canonical byte sequence β a deterministic, ordered sequence of bytes that satisfies:
1. Determinism: The same representation graph always produces the same canonical byte sequence (URS I21). 2. Structural identity preservation: Two structurally identical graphs (URS Β§4.1, L1) produce identical canonical byte sequences (URS I22). 3. Cycle safety: Graphs containing cycles serialize deterministically without infinite recursion (URS I23). 4. Codec independence: The canonical byte sequence does not depend on any particular serialization codec.
1.2 Canonical Form vs Canonical Serialization
| Term | Definition | Produced By |
|---|---|---|
| Canonical Form | The normalized representation graph after applying all canonicalization rules but before serialization | This spec, Β§1βΒ§4 |
| Canonical Byte Sequence | The canonical form serialized to a deterministic byte order | This spec, Β§5 |
| Canonical Hash | SHA-256 of the canonical byte sequence | This spec, Β§6 |
| Canonical Serialization | A codec-specific byte output (e.g., canonical JSON, canonical CBOR) | JSON-CORE-LD Β§5, CBOR-CORE-LD Β§5 |
A codec's canonical serialization SHALL decode to the canonical form defined here but MAY produce different bytes (different encoding, same structural identity).
Section 2: Normalization Algorithm
2.1 Algorithm Overview
The URS Canonicalization algorithm proceeds in six phases:
1. Entity enumeration β collect all Entities in the representation graph 2. Kind assignment β confirm each Entity's kind and derive its canonical properties 3. Identifier normalization β relabel all Local Identifiers to deterministic blank node labels 4. Property normalization β canonicalize all Property names and values 5. Graph normalization β canonicalize Link structure, Group membership, and containment 6. Ordering β apply canonical ordering to all unordered structures
2.2 Phase 1: Entity Enumeration
Enumerate all Entities reachable from the root Entity via Properties (Entity references), Links (source/target), and Group membership. The enumeration is a depth-first traversal starting from the root (URS I11), using canonical ordering rules at each level (URS Β§4.3) to ensure determinism.
Traversal order: 1. Visit root Entity 2. For each Property on the Entity (ordered by Property name), if the Property value references another Entity, visit that Entity 3. For each Link where this Entity is the source (ordered by Link type, then target Identifier), visit the target Entity 4. For each Group this Entity is a member of (ordered by Group Identifier), visit the Group Entity 5. For each member of a Group (ordered by canonical member order), visit the member Entity 6. Maintain a visited-Entity set. If an Entity has been visited, do not revisit (cycle termination)
2.3 Phase 2: Kind Assignment
For each Entity, confirm its Representation Kind is one of the five declared kinds (URS I1): entity, property, identifier, link, group.
Derive the canonical kind properties for each kind per URS Β§4.6:
| Kind | Canonical Properties |
|---|---|
| Entity | Identifier, Properties, Links, Group membership |
| Property | Name, Value, owning Entity reference |
| Identifier | Value string, Scope (local/constitutional), Type (if declared) |
| Link | Source Entity reference, Target Entity reference, Link Type, optional Properties |
| Group | Variant (Set/Sequence/Map), Members or Entries |
CORE-LD alignment: in the CORE-LD family, kinds are expressed via @type on framed documents (JSON-CORE-LD Β§3.2, CBOR-CORE-LD Β§3.2), with kind retained as an alias for URS-kind documents:
| URS kind | CORE-LD `@type` | Notes |
|---|---|---|
| `entity` | `Entity` | Root and satellite entities |
| `property` | `Property` | Name/value pairs embedded on owners in framing |
| `identifier` | `Identifier` | Explicit `identifier` object (scope, canonicalHash) |
| `link` | `Link` | Members of the `links` container |
| `group` | `Group` | `groupVariant`: Set / Sequence / Map |
2.4 Phase 3: Identifier Normalization
Local Identifier normalization follows a deterministic relabeling algorithm:
1. Collect all Local Identifiers in the graph. 2. Sort them by their first appearance in the Phase 1 depth-first traversal order. 3. Assign each a canonical blank node label: _:b0, _:b1, _:b2, ... in traversal order. 4. Replace all references to the original Local Identifier with the canonical label.
Constitutional Identifiers are never normalized. They are preserved verbatim (URS Β§4.4).
Cross-context Identifiers are resolved to their canonical form within their declaring context before comparison (URS Β§4.4).
Normalization invariant: After normalization, two structurally identical representations that differ only in their original Local Identifier names will have identical normalized forms.
2.5 Phase 4: Property Normalization
Property name normalization: 1. Property names are normalized to Unicode NFC (Normalization Form Canonical Composition). 2. After NFC normalization, Property names are compared as byte sequences.
Property value normalization:
| Value Type | Normalization Rule |
|---|---|
| `null` | Retained as null β no transformation |
| `boolean` | Retained as boolean β no transformation |
| `integer` | Retained as integer β no transformation |
| `float` | Retained as float β no transformation |
| `string` | Normalized to Unicode NFC, then retained |
| `bytes` | Retained as byte sequence β no transformation |
| Entity reference | Replaced with the target Entity's canonical Identifier after normalization (Β§2.4) |
| Link | Normalized per Β§2.6 |
2.6 Phase 5: Graph Normalization
Link normalization: 1. Source: replaced with the source Entity's canonical Identifier. 2. Target: replaced with the target Entity's canonical Identifier. 3. Link Type: normalized to NFC string. 4. Link Properties: normalized per Β§2.5. 5. Link ordering: primary by Link Type (byte-ordered), then by target Identifier (byte-ordered), then by canonical hash of Link Properties.
Group normalization: 1. Variant declared explicitly (Set, Sequence, or Map). 2. Set members: normalized by replacing each member reference with the member's canonical Identifier. Duplicates removed. Members ordered by canonical Identifier (byte-ordered). 3. Sequence members: normalized by replacing each member reference with the member's canonical Identifier. Order preserved as declared. 4. Map entries: normalized by replacing each value reference with the entry's canonical Identifier. Keys ordered by byte-ordered UTF-8. 5. Nested Groups normalized recursively.
2.7 Phase 6: Ordering
Apply canonical ordering per URS Β§4.3:
1. Properties within an Entity β ordered lexicographically by normalized Property name (UTF-8 byte order). 2. Links from a single source Entity β ordered by Link type (byte-ordered), then target Identifier (byte-ordered), then Link Properties hash. 3. Set members β ordered by canonical Identifier (byte-ordered). 4. Sequence members β order preserved as declared. 5. Map entries β ordered by key (byte-ordered UTF-8). 6. At document/representation level β provenance fields ordered: Representer, Timestamp, Authority, RepresentationContext, PriorState (if present).
Section 3: Content-Addressing Model
3.1 Canonical Byte Sequence
After normalization (Phases 1β6), the canonical representation graph is serialized to a canonical byte sequence:
1. Serialize each Entity as an ordered key-value structure (key-order determined by Phase 6). 2. Serialize the complete graph as an ordered array of Entities, ordered by their canonical Identifier (byte-ordered). 3. Output as a deterministic byte sequence using the URS Canonical Binary Format (defined below).
3.2 URS Canonical Binary Format
The canonical binary format is a minimal, deterministic binary encoding designed specifically for URS canonicalization. It is NOT a general-purpose serialization β it exists solely to produce the canonical byte sequence for hashing and identity binding.
| Type | Encoding | Byte Count |
|---|---|---|
| Null | `0x00` | 1 |
| Boolean false | `0x01` | 1 |
| Boolean true | `0x02` | 1 |
| Integer (positive, <= 2βΆΒ³-1) | `0x10` + varint value | 1β9 |
| Integer (negative, >= -2βΆΒ³) | `0x11` + varint absolute value | 1β9 |
| Float (IEEE 754 double) | `0x20` + 8 bytes big-endian | 9 |
| String | `0x30` + varint byte length + UTF-8 bytes | 2+ |
| Bytes | `0x40` + varint byte length + raw bytes | 2+ |
| Array (ordered) | `0x50` + varint element count + elements | 2+ |
| Map (ordered key-value) | `0x60` + varint entry count + key-value pairs | 2+ |
| Reference (to Entity by canonical Identifier) | `0x70` + serialized canonical Identifier string | 2+ |
Key ordering in maps: Byte-ordered by the key's serialized bytes. This is deterministic by construction.
Empty structures: An empty array is 0x50 0x00. An empty map is 0x60 0x00.
3.3 Content Identifier (CHash)
The Content Hash (CHash) of a URS representation is:
CHash = multihash(SHA-256(canonical_byte_sequence))
Where:
- `canonical_byte_sequence` is the output of Β§3.1
- `SHA-256` produces 32 bytes
- `multihash` wraps the hash in the standard multihash format: `
`
Multihash parameters (default):
- Hash function: SHA-256 (multihash code `0x12`)
- Digest length: 32 bytes
- Full multihand: `0x12 0x20` + 32 bytes = 34 bytes total
Multihash code registry (for URS Canonicalization):
| Code | Hash Function | Digest Length | Notes |
|---|---|---|---|
| `0x12` | SHA-256 | 32 bytes | Default β MUST be supported by all implementations |
| `0x13` | SHA-384 | 48 bytes | Optional β for stronger binding |
| `0x16` | SHA-256 (truncated) | 16 bytes | Optional β for space-constrained contexts |
| `0x1B` | Blake3-256 | 32 bytes | Optional β faster hashing |
3.4 Structural Identifier (SID)
The Structural Identifier (SID) is the CHash of the structural identity (L1) of a representation β excluding all provenance, authority, and constitutional identity metadata. This enables content-addressed identification of "what the data is" independently of "who asserted it."
Two representations that differ only in their provenance but have identical structural content will share the same SID but have different CHashes.
Identity-level alignment with CORE-LD (CORE-LD Β§3.1):
| CORE-LD level | Identifier | Exclusion set | Defined in |
|---|---|---|---|
| L1 structural | SID (structural identity) | Provenance, authority, constitutional metadata | This spec Β§3.4 |
| L2 content | L2 content hash | `@context` declaration **and** provenance (identifiers + properties only) | JSON-CORE-LD Β§5.2, CBOR-CORE-LD Β§5.2 |
| L3 constitutional | CHash (full content) | Nothing β the complete representation including provenance | This spec Β§3.3 |
The exclusion sets are intentionally different: SID operates at the representation level (provenance removed), while the L2 content hash is defined per encoding binding and additionally strips the @context declaration for encoding-agnostic identity. All three are computed by the same normalization pipeline (Β§2) and serialized per Β§3.1β3.2.
Section 4: Canonical Hash Computation
4.1 Hash Binding
URS uses canonical hashes for three binding purposes:
| Purpose | Hash Used | Bound To | Invariant |
|---|---|---|---|
| **Content identity** | CHash (Β§3.3) | The complete representation including provenance | I21, I22 |
| **Structural identity** | SID (Β§3.4) | The representation structure excluding provenance | I22 |
| **Constitutional identity** | CHash of attested form | The signed canonical hash in a Constitutional Identifier | I12, I13 |
4.2 Hash Computation Steps
To compute the CHash of a URS representation:
1. Extract the representation graph from the root Entity 2. Normalize the graph per Β§2 (Phases 1β6) 3. Serialize the normalized graph to canonical binary format per Β§3.1β3.2 4. Hash the byte sequence with SHA-256 per Β§3.3 5. Wrap in multihash per Β§3.3
The resulting 34-byte value is the CHash.
4.3 SID Computation
Same steps as CHash, but with provenance fields (Β§6.1 provenance record) removed from the representation graph before normalization and serialization.
Section 5: Codec Identifiers
5.1 Standard Codec Identifiers
Each URS codec SHALL be assigned a canonical codec identifier used in content addressing and cross-codec interop. The registry is maintained as part of this specification.
Active codecs (CORE-LD family, v0.1.0):
| Codec | Identifier | Multicodec Code | MIME Type |
|---|---|---|---|
| URS Canonical Binary (this spec) | `urs-cbor` | `0x03E9` (prototype) | `application/vnd.icore.urs-cb` |
| JSON-CORE-LD (encoding binding) | `json-core-ld` | `0x0129` (`dag-json`) when DAG-addressed | `application/json` (canonical), `application/ld+json` |
| CBOR-CORE-LD (encoding binding) | `cbor-core-ld` | `0x71` (`dag-cbor`) when DAG-addressed | `application/cbor` (canonical), `application/ld+cbor` |
Historical codecs (superseded, retained on record):
| Codec | Identifier | Multicodec Code | MIME Type |
|---|---|---|---|
| DAG-JSON-LD (pre-CORE-LD draft) | `dag-json-ld` | `0x03EA` (prototype) | `application/vnd.icore.dag-json-ld` |
| DAG-CBOR-LD (pre-CORE-LD draft) | `dag-cbor-ld` | `0x03EB` (prototype) | `application/vnd.icore.dag-cbor-ld` |
| DAG-Constitution-LD (draft) | `dag-constitution-ld` | `0x03EC` (prototype) | `application/vnd.icore.dag-constitution-ld` |
The active CORE-LD bindings use the standard multicodec codes (dag-json 0x0129, dag-cbor 0x71) for DAG-addressed use β no prototype codes needed. A DAG address (Β§5.3) therefore reads identically whether produced by IPLD tooling or a URS implementation for the same underlying document.
5.2 Codec Identifier Resolution
Given a codec identifier CID and a canonical byte sequence CBS (from Β§3.1), a codec's canonical serialization is:
Serialize(CID, CBS) β codec-specific bytes
A conforming codec SHALL guarantee:
Decompress(codec_bytes) β CBS β CHash β matches declared CHash
5.3 DAG Addressing Mode
CORE-LD Β§6.2 defines addressing modes as an axis of the dimensional architecture: [Addr]-[Encoding]-[Profile]-LD. The DAG addressing mode makes a CORE-LD document content-addressed: its address is derived entirely from its canonical bytes, independent of location.
Address construction (byte form):
DAG address = <multicodec codec varint> ++ <multihash>
where <multihash> is the CHash (Β§3.3) of the representation. For CBOR-CORE-LD documents this is 0x71 ++ 0x12 0x20 ++ <32 bytes>; for JSON-CORE-LD documents 0xA9 0x02 ++ 0x12 0x20 ++ <32 bytes> (dag-json varint). The text form is multibase z-prefixed base58btc of the same bytes (CIDv1-style; a version varint 0x01 precedes the codec when full IPLD CID compatibility is required).
Properties:
1. Content-derived β the address changes iff the canonical bytes change (I21, I22). Provenance edits β different CHash β different address; structural-only edits likewise. 2. Label-stable (canonicalization level) β Local Identifier relabeling (Β§2.4) is applied before hashing, so two representations differing only in _: label names share the same CHash, and hence the same canonicalization-level DAG address. Binding-level block addresses (CBOR-CORE-LD Β§5.2 L2 over the framed document's canonical CBOR, IPLD-style) hash the actual block bytes and are label-sensitive β the _: labels are part of the block. C6 (Β§7) defines the conversion between the two domains. 3. Codec-distinct β the codec varint disambiguates the encoding; a JSON-CORE-LD and a CBOR-CORE-LD document with the same logical content carry different addresses. 4. Resolution β within a DAG-addressed document, entity references resolve via @id; references outside the document resolve to other DAG addresses (external links).
Addressing mode composition: DAG-JSON-LD and DAG-CBOR-LD (CORE-LD Β§6.2 naming) denote the DAG-addressed forms of the JSON-CORE-LD and CBOR-CORE-LD bindings respectively β the naming is inherited from the historical codec drafts, the addressing rules from this section.
Section 6: Cycle Handling in Canonicalization
6.1 Cycle Detection
The canonicalization algorithm MUST detect cycles during the Phase 1 traversal. Detection uses a visited-Entity map (by canonical Identifier). When an Entity is encountered that is already in the visited set, a cycle is recorded rather than recursing.
6.2 Cycle Documentation in Canonical Form
A cycle in the canonical form is recorded as:
[cycle:
[0]: Entity canonical Identifier
[1]: Link type that forms the back-edge
[2]: Source Entity canonical Identifier (cycle origin)
[3]: Link chain (array of [source, link type, target] tuples)
]
The cycle structure ensures deterministic serialization without infinite recursion (URS I23).
6.3 Self-Containing Group Detection
A Group that contains itself directly or transitively (URS I10) is invalid and MUST cause canonicalization to fail with an error. This is detected during Phase 1 traversal: if a Group Entity appears in its own membership chain, canonicalization halts.
Section 7: Invariants
This specification contributes the following invariants beyond the CORE-LD invariants I1βI23:
| # | Invariant | Mechanical Verification |
|---|---|---|
| C1 | Canonicalization of the same representation graph SHALL produce the same canonical byte sequence on every invocation. | Run canonicalization twice on the same graph. Byte-compare output. Any difference is an implementation error. |
| C2 | Two representations that are structurally identical (URS Β§4.1, L1) with different Local Identifier names SHALL produce identical canonical byte sequences. | Given two structurally identical graphs with different local names, confirm their canonical byte sequences are identical. |
| C3 | A representation containing a permitted cycle SHALL serialize deterministically without infinite recursion. | For each detected cycle, confirm the canonical form documents the cycle structure using the format in Β§6.2. |
| C4 | The canonical hash (CHash) of a representation SHALL match the `canonicalHash` declared in any Constitutional Identifier bound to an Entity in that representation. | Compute CHash. Compare with the declared `canonicalHash` value. Reject on mismatch. |
| C5 | A codec canonical serialization SHALL decompress to the same canonical byte sequence produced by Β§3.1β3.2. | Given a codec-specific serialization, decompress to representation graph, then run canonicalization. Compare with original canonical byte sequence. |
| C6 | A CORE-LD encoding binding's canonical hash (JSON-CORE-LD Β§5.2, CBOR-CORE-LD Β§5.2) SHALL be computed over that binding's canonical serialization of the canonical form, SHALL be stable across invocations, and SHALL be convertible to the CHash of Β§3.3 via the binding's decompression rules. | Encode the same representation twice via the binding; byte-compare hash inputs. Decompress the binding's canonical serialization; run Β§2; confirm CHash is reproducible. |
C1βC5 map to the CORE-LD canonicalization invariants (I21 determinism, I22 structural identity β same hash, I23 cycle-safe serialization; CORE-LD Β§7.5). C6 fixes the relationship between the binding-level hashes (defined over canonical JSON/CBOR bytes) and the canonicalization-level CHash (defined over the URS Canonical Binary): different byte forms, same structural identity β each is independently reproducible, and Β§5.2 resolution converts between them.
Section 8: Examples
8.1 Minimal Entity Normalization
Before normalization (with local identifiers):
Root Entity (Local: "_:myDevice")
Properties:
- name: "Device-001"
- type: "sensor"
Identifier: "_:myDevice"
After normalization:
Root Entity (Local: "_:b0")
Properties:
- name: "Device-001"
- type: "sensor"
Identifier: "_:b0"
Canonical byte sequence (hex):
50 01 # array(1) β the graph, one entity
60 02 # map(2) β entity sections
30 0A 49 64 65 6E 74 69 66 69 65 72 # text(10) "Identifier"
30 04 5F 3A 62 30 # text(4) "_:b0" β canonical blank label
30 0A 50 72 6F 70 65 72 74 69 65 73 # text(10) "Properties"
60 02 # map(2) β two properties
30 04 6E 61 6D 65 # text(4) "name"
30 0A 44 65 76 69 63 65 2D 30 30 31 # text(10) "Device-001"
30 04 74 79 70 65 # text(4) "type"
30 06 73 65 6E 73 6F 72 # text(6) "sensor"
The byte sequence above is the verified output of the reference implementation (canonicalize in urs_canonicalization.py); the conformance suite extracts this block and asserts byte-equality with the implementation output (Β§8.5).
8.2 Graph with Two Entities and a Link
Before normalization:
Entity A (Local: "_:node1")
Properties: name = "Server"
Links: β B via "connectsTo"
Entity B (Local: "_:node2")
Properties: name = "Database"
Links: β A via "connectsTo" (cycle)
After normalization:
Entity _:b0
Properties: name = "Server"
Links: [connectsTo β _:b1]
Entity _:b1
Properties: name = "Database"
Links: [connectsTo β _:b0]
Cycle: [_:b1, connectsTo, _:b0, [[_:b0, connectsTo, _:b1]]]
8.3 CHash Calculation
Given the normalized representation from 8.1, the canonical byte sequence is:
50 01 60 02 30 0A 49 64 65 6E 74 69 66 69 65 72 30 04 5F 3A 62 30 30 0A 50 72 6F 70 65 72 74 69 65 73 60 02 30 04 6E 61 6D 65 30 0A 44 65 76 69 63 65 2D 30 30 31 30 04 74 79 70 65 30 06 73 65 6E 73 6F 72
(68 bytes β the verified output of canonicalize(); array wrapper 0x50 0x01 per Β§3.1, string markers 0x30 per the Β§2.3 format table.)
CHash = SHA-256(above bytes) = 12 20 28 5F F6 81 25 8D 69 FF F5 B1 42 15 43 5A 41 95 B1 79 E0 DD DE 44 5F 04 A1 05 B9 F1 FE 3E 4F A3 (34 bytes: multihash 0x12 SHA-256, 0x20 length 32, 32-byte digest).
8.4 DAG Address Computation
Given the CHash from Β§8.3 (0x12 0x20 ++ <32 digest bytes>), the DAG address of the document as CBOR-CORE-LD is:
dag-cbor varint: 0x71
multihash: 0x12 0x20 <32 digest bytes>
address (bytes): 0x71 0x12 0x20 <32 digest bytes> (35 bytes)
address (text): z + base58btc(above 35 bytes) (multibase z)
The same document addressed as JSON-CORE-LD carries the dag-json varint 0xA9 0x02 instead β codec-distinct addresses for the same logical content (Β§5.3 property 3).
8.5 Conformance Suite
The reference suite is test_urs_canonicalization.py (24 tests, all passing), exercising:
- C1 β determinism (repeated canonicalization byte-identical), non-canonical-input rejection (opaque integer map keys)
- C2 β relabel-stability (structurally identical docs differing only in `_:` label names canonicalize identically), opaque group-Map entry keys correctly treated as structural (relabeling changes them β different canonical form)
- C3 β cycle-safe serialization (deterministic bytes, cycle structure documented per Β§6.2, cycle record format byte-matched to the Β§8.2 example), self-containing Group rejection (I10 halt)
- C4 β `canonicalHash` declaration consistency (match β pass, mismatch β fail)
- C5 β binding round-trip: canonical JSON (JSON-CORE-LD Β§5.1) β CBOR-CORE-LD encode β canonicalize β byte-identical to direct canonicalization
- C6 β CBOR-CORE-LD L2/L3 hash stability and provenance-exclusion semantics (documents differing only in provenance share L2, differ at L3)
- Β§8.1/Β§8.3 examples β hex block extracted from the spec markdown and asserted byte-equal to `canonicalize()` output; CHash asserted byte-equal to the spec's documented digest
The suite reuses the CORE-LD family fixtures (test_cbor_core_ld.EXAMPLES, profile_conformance.build_doc) and the deterministic CBOR encoder (cbor_core_ld.py) for the C5/C6 binding checks.
Section 9: Constitutional Layer
| Property | Value |
|---|---|
| Companion to | URS Formal Specification v0.1.0; aligned to CORE-LD v0.1.0 (July 31, 2026) |
| Layer | 3 (Representation) β companion, not independent |
| Versioning | Independent β algorithms may be revised without touching URS data model |
| Depends on | URS Β§4 (Canonical Rules), CORE-LD Β§7 (Invariants I1βI23, incl. I21βI23 in Β§7.5) |
| Depended on by | JSON-CORE-LD (Β§5), CBOR-CORE-LD (Β§5), all CORE-LD encoding bindings for hash computation and DAG addressing (Β§5.3) |
| Governance status | **Frozen-readiness** β conformance suite verified (24 tests, Β§8.5); formal freeze pending UCF artifact compilation |
Doctrine Position
| Doctrine Principle | URS Canonicalization Position |
|---|---|
| Constitution before architecture | Canonicalization is architecture, not constitution β it is an algorithm, not a rule. The constitutional rules are in URS Β§4 / CORE-LD Β§7. |
| Separately versioned | The canonicalization algorithms may be revised without touching the frozen URS data model. |
| Deterministic by construction | Same input β same output on every invocation, across any conforming implementation. |
| Codec independent | Canonical form is codec-agnostic. All encoding bindings produce the same canonical byte sequence for the same representation. |
| Content addressing | The DAG addressing mode (Β§5.3) makes addresses content-derived, label-stable, and codec-distinct β addresses are facts about bytes, not about locations. |
| Strict about outcomes, tolerant about methods | The canonical hash is the outcome. Any implementation producing the same hash for the same representation is conformant regardless of internal representation. |
End of URS Canonicalization Specification v0.1.0