code wiki / (root) / nx_uxf_cid.nx

nx_uxf_cid.nx source

↩ module page · 70 lines · 3173 B

1// nx_uxf_cid.nx -- UXF arc R1c: the SELF-DESCRIBING multicodec/profile CID, built ON TOP 2// of nx_canon_cid (do NOT touch the foundation -- Rule 19 additive, Rule 3 no patch cascade). 3// 4// The substrate spec (knowledge/specs/2026-06-09-tutoring-storage-substrate-rung1.md) defines 5// CID = multihash + a multicodec(record-type) tag, but the shipped cid_of() omits the 6// multicodec. This adds it. The profiled CID carries a PROFILE/codec id that is: 7// (a) FOLDED INTO the hash -> same bytes under different profiles => different CID 8// (no cross-profile collision; still fully content-addressed within a profile), AND 9// (b) READABLE from the CID string -> an endpoint can pick the right view WITHOUT any 10// out-of-band schema = Law-1 endpoint-adaptive ; new profiles = new codec ids with 11// NO format change = Law-4 extensible (Rule 25: add an id, never a new format). 12// 13// Profiled CID: "nxc1-" <2hex codec> "-" <64hex sha256(codec_byte || canon_bytes)> NUL (len 72) 14// No hardware/persistent writes (Rule 26). license_tier: ORIGINAL 15import "nx_syscalls.nx" 16import "nx_sha256.nx" 17import "nx_canon_cid.nx" 18 19// UXF profile/codec ids (the multicodec tag) -- the data-driven extension point. 20const UXF_DATA: i64 = 1 21const UXF_DOC: i64 = 2 22const UXF_MEDIA: i64 = 3 23const UXF_CONFIG: i64 = 4 24const UXF_ARCHIVE: i64 = 5 25const UXF_SEARCH: i64 = 6 // a search answer (search rung E8, 2026-09-14): query, corpus, hits -- JSON and text are its projections 26const UXF_CID_LEN: i64 = 72 // the profiled CID's width, derived: 5 (nxc1-) + 2 (codec hex) + 1 (-) + 64 (sha256 hex); callers size cid buffers UXF_CID_LEN + 1 27 28func uxf_nib_hex(v: i64) -> i64 { 29 if v > 9 { return 87 + v } // a-f 30 return 48 + v // 0-9 31} 32 33func uxf_hex_nib(b: i64) -> i64 { 34 if b >= 48 { if b <= 57 { return b - 48 } } // 0-9 35 if b >= 97 { if b <= 102 { return b - 87 } } // a-f 36 if b >= 65 { if b <= 70 { return b - 55 } } // A-F 37 return 0 - 1 38} 39 40// profiled CID = "nxc1-" + 2hex(codec) + "-" + 64hex(sha256(codec || canon)); writes NUL; returns 72. 41func uxf_cid_profiled(codec: i64, canon: *u8, n: i64, cid: *u8) -> i64 { 42 let tmp: *u8 = sys_mmap(n + 16) 43 tmp[0] = (codec & 0xff) as u8 44 var i: i64 = 0 45 while i < n { tmp[1 + i] = canon[i]; i = i + 1 } 46 let dg: *u8 = sys_mmap(40) 47 sha256_digest(tmp, n + 1, dg) 48 cid[0] = 110 as u8; cid[1] = 120 as u8; cid[2] = 99 as u8; cid[3] = 49 as u8; cid[4] = 45 as u8 49 cid[5] = uxf_nib_hex((codec >> 4) & 15) as u8 50 cid[6] = uxf_nib_hex(codec & 15) as u8 51 cid[7] = 45 as u8 52 i = 0 53 while i < 32 { 54 let b: i64 = dg[i] & 0xff 55 cid[8 + i * 2] = uxf_nib_hex((b >> 4) & 15) as u8 56 cid[9 + i * 2] = uxf_nib_hex(b & 15) as u8 57 i = i + 1 58 } 59 cid[UXF_CID_LEN] = 0 as u8 60 return UXF_CID_LEN 61} 62 63// READ the profile/codec back out of a profiled CID (self-describing); (0-1) if malformed. 64func uxf_codec_of_cid(cid: *u8) -> i64 { 65 let hi: i64 = uxf_hex_nib(cid[5] as i64) 66 let lo: i64 = uxf_hex_nib(cid[6] as i64) 67 if hi < 0 { return 0 - 1 } 68 if lo < 0 { return 0 - 1 } 69 return (hi * 16) + lo 70}