nx_ident.nx source
↩ module page · 223 lines · 9646 B
1// nx_ident.nx -- ARTIFACT IDENTITY ORACLE: "which binary is ACTUALLY running,
2// and does it match anything I built?"
3//
4// WHY THIS EXISTS (four self-corrections in one session, 2026-07-30):
5// 1. I debugged a "commit SEGV" in nx_mvault_walk for a long arc. There was
6// no bug. A promote that returned FETCH-FAIL had SUCCEEDED, a rollback
7// that died on a closed socket had ALSO applied, and the live elf ended up
8// at 156,572 B -- matching NEITHER my build (229,700) NOR .prev (193,788)
9// NOR .prev-vw02b (164,804). The symptom was a STALE ARTIFACT, not code.
10// 2. I declared a freshly-built mgmt binary "wedged on startup". An A/B on
11// throwaway ports cleared it; the real defect was elsewhere.
12// Both collapse to ONE missing capability: no cheap way to ask WHAT IS LIVE.
13//
14// ★★★★★LAW: BEFORE DEBUGGING A BEHAVIOUR, PROVE WHICH ARTIFACT IS EXECUTING.
15// A symptom is only evidence about the bytes that actually ran.
16//
17// THE VERDICT THAT MATTERS MOST is LIVE-MATCHES-NOTHING: the live binary is
18// byte-sized like no build, no .prev, and no banked variant. That is the
19// signature of a half-applied deploy/rollback -- exactly case (1) -- and it is
20// the state in which every downstream conclusion is worthless. It is reported
21// LOUDLY rather than folded into "stale", because its remedy is different:
22// stale means "promote"; matches-nothing means "STOP, establish provenance".
23//
24// nx_ident <organ-name> e.g. nx_ident nx_mvault_walk
25//
26// Reports live / staged / prev / every banked <name>.* variant with BYTES, and
27// a verdict. Read-only. license_tier: ORIGINAL No hw writes (Rule 26).
28
29import "nx_syscalls.nx"
30
31const ID_DIRBUF: i64 = 1048576
32const ID_MAXV: i64 = 64 // variants reported; overflow is DECLARED
33const ID_NAME: i64 = 256
34const ID_OUT: i64 = 65536
35const ID_SEEK_END: i64 = 2
36
37func id_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
38
39func id_cat(d: *u8, o: i64, s: *u8) -> i64 {
40 var p: i64 = o
41 var i: i64 = 0
42 while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 }
43 return p
44}
45
46func id_ch(d: *u8, o: i64, c: i64) -> i64 { d[o] = c as u8; return o + 1 }
47
48func id_dec(d: *u8, o: i64, v: i64) -> i64 {
49 if v < 0 { return id_cat(d, o, "-1" as *u8) }
50 if v == 0 { d[o] = 48 as u8; return o + 1 }
51 let t: *u8 = sys_mmap(32)
52 var m: i64 = v
53 var k: i64 = 0
54 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
55 var p: i64 = o
56 var i: i64 = k - 1
57 while i >= 0 { d[p] = t[i]; p = p + 1; i = i - 1 }
58 sys_munmap(t, 32)
59 return p
60}
61
62// byte length of a file, or -1 when absent/unopenable
63func id_size(path: *u8) -> i64 {
64 let fd: i64 = sys_openat_rd(path)
65 if fd < 0 { return 0 - 1 }
66 let n: i64 = sys_lseek(fd, 0, ID_SEEK_END)
67 sys_close(fd)
68 return n
69}
70
71// does `name` start with `pfx`?
72func id_starts(name: *u8, pfx: *u8) -> i64 {
73 var i: i64 = 0
74 while pfx[i] != (0 as u8) {
75 if name[i] != pfx[i] { return 0 }
76 i = i + 1
77 }
78 return 1
79}
80
81func id_eq(a: *u8, b: *u8) -> i64 {
82 var i: i64 = 0
83 while 1 == 1 {
84 if a[i] != b[i] { return 0 }
85 if a[i] == (0 as u8) { return 1 }
86 i = i + 1
87 }
88 return 0
89}
90
91func main(argc: i64, argv: *i64) -> i64 {
92 if argc < 2 {
93 sys_write(2, "usage: nx_ident <organ-name>\n" as *u8, 29)
94 return 2
95 }
96 let nm: *u8 = (argv[1]) as *u8
97
98 // canonical roles
99 let live: *u8 = sys_mmap(ID_NAME)
100 let stag: *u8 = sys_mmap(ID_NAME)
101 let prev: *u8 = sys_mmap(ID_NAME)
102 var o1: i64 = id_cat(live, 0, nm); o1 = id_cat(live, o1, ".elf" as *u8); live[o1] = 0 as u8
103 var o2: i64 = id_cat(stag, 0, nm); o2 = id_cat(stag, o2, ".sov.elf.new" as *u8); stag[o2] = 0 as u8
104 var o3: i64 = id_cat(prev, 0, nm); o3 = id_cat(prev, o3, ".elf.prev" as *u8); prev[o3] = 0 as u8
105
106 let live_b: i64 = id_size(live)
107 let stag_b: i64 = id_size(stag)
108 let prev_b: i64 = id_size(prev)
109
110 // scan CWD for EVERY banked variant "<name>." so MATCHES-NOTHING is
111 // trustworthy -- a verdict that only checked 3 names could call a legit
112 // banked artifact "unknown".
113 let pfx: *u8 = sys_mmap(ID_NAME)
114 var op: i64 = id_cat(pfx, 0, nm); pfx[op] = 46 as u8; pfx[op + 1] = 0 as u8
115 let dbuf: *u8 = sys_mmap(ID_DIRBUF)
116 let vname: *i64 = sys_mmap(8 * ID_MAXV) as *i64
117 let vsize: *i64 = sys_mmap(8 * ID_MAXV) as *i64
118 let arena: *u8 = sys_mmap(ID_MAXV * ID_NAME)
119 var ao: i64 = 0
120 var nv: i64 = 0
121 var overflow: i64 = 0
122 var matched: i64 = 0 // live bytes equal some non-live artifact?
123
124 let dfd: i64 = sys_openat_rd("." as *u8)
125 if dfd >= 0 {
126 var done: i64 = 0
127 while done == 0 {
128 let nread: i64 = sys_getdents64(dfd, dbuf, ID_DIRBUF)
129 if nread <= 0 { done = 1 } else {
130 var off: i64 = 0
131 while off < nread {
132 let drec: *u8 = ((dbuf as i64) + off) as *u8
133 let reclen: i64 = dirent_reclen(drec)
134 let name: *u8 = dirent_name(drec)
135 if id_starts(name, pfx) == 1 {
136 if id_eq(name, live) == 0 {
137 if nv >= ID_MAXV { overflow = overflow + 1 } else {
138 let sz: i64 = id_size(name)
139 let dst: *u8 = ((arena as i64) + ao) as *u8
140 var c: i64 = 0
141 while name[c] != (0 as u8) { dst[c] = name[c]; c = c + 1 }
142 dst[c] = 0 as u8
143 vname[nv] = dst as i64
144 vsize[nv] = sz
145 ao = ao + c + 1
146 nv = nv + 1
147 if sz == live_b { if live_b > 0 { matched = matched + 1 } }
148 }
149 }
150 }
151 if reclen <= 0 { off = nread } else { off = off + reclen }
152 }
153 }
154 }
155 sys_close(dfd)
156 }
157
158 let out: *u8 = sys_mmap(ID_OUT)
159 var o: i64 = 0
160 o = id_cat(out, o, "=== nx_ident -- WHICH ARTIFACT IS ACTUALLY EXECUTING ===\norgan=" as *u8)
161 o = id_cat(out, o, nm)
162 o = id_cat(out, o, "\n live " as *u8); o = id_cat(out, o, live)
163 o = id_cat(out, o, " bytes=" as *u8); o = id_dec(out, o, live_b)
164 o = id_cat(out, o, "\n staged " as *u8); o = id_cat(out, o, stag)
165 o = id_cat(out, o, " bytes=" as *u8); o = id_dec(out, o, stag_b)
166 o = id_cat(out, o, "\n prev " as *u8); o = id_cat(out, o, prev)
167 o = id_cat(out, o, " bytes=" as *u8); o = id_dec(out, o, prev_b)
168 o = id_ch(out, o, 10)
169 o = id_cat(out, o, " banked variants=" as *u8); o = id_dec(out, o, nv)
170 if overflow > 0 {
171 o = id_cat(out, o, " OVERFLOW=" as *u8); o = id_dec(out, o, overflow)
172 o = id_cat(out, o, " (raise ID_MAXV; NOT a silent cap)" as *u8)
173 }
174 o = id_ch(out, o, 10)
175 var i: i64 = 0
176 while i < nv {
177 o = id_cat(out, o, " " as *u8)
178 o = id_cat(out, o, (vname[i]) as *u8)
179 o = id_cat(out, o, " bytes=" as *u8)
180 o = id_dec(out, o, vsize[i])
181 if vsize[i] == live_b { if live_b > 0 { o = id_cat(out, o, " <== SAME SIZE AS LIVE" as *u8) } }
182 o = id_ch(out, o, 10)
183 i = i + 1
184 }
185
186 o = id_cat(out, o, "\nNX-IDENT verdict=" as *u8)
187 var rc: i64 = 0
188 if live_b < 0 {
189 o = id_cat(out, o, "NO-LIVE (nothing deployed under that name)\n" as *u8)
190 rc = 3
191 } else {
192 if live_b == stag_b {
193 o = id_cat(out, o, "LIVE-IS-STAGED -- the running bytes match the current build.\n" as *u8)
194 rc = 0
195 } else {
196 // ⚠SELF-CORRECTION 2026-07-30, caught by this tool ON ITS OWN FIRST
197 // RUN: /api/promote CONSUMES the staged .sov.elf.new, so a CORRECTLY
198 // promoted organ has no staged artifact to compare against. Calling
199 // that MATCHES-NOTHING conflated ABSENCE OF EVIDENCE with
200 // CONTRADICTORY EVIDENCE -- the exact error class this organ exists
201 // to prevent. UNVERIFIABLE is the honest verdict, and it is a
202 // DIFFERENT remedy: matches-nothing means "stop, establish
203 // provenance"; unverifiable means "the ecosystem kept no record".
204 // ★THE DEEPER GAP: promote DESTROYS the provenance record. The fix
205 // is a promote LEDGER -- the current mgmt already emits sha256 on
206 // promote, so nx_ident should verify live's digest against it.
207 if stag_b < 0 {
208 o = id_cat(out, o, "UNVERIFIABLE -- no staged build to compare against (promote consumes it). NOT evidence of a problem, and NOT proof of health: provenance simply was not recorded. Verify against the promote ledger sha256.\n" as *u8)
209 rc = 2
210 } else {
211 if matched > 0 {
212 o = id_cat(out, o, "LIVE-BEHIND-STAGED -- live matches a BANKED artifact but not the staged build; promote to ship it.\n" as *u8)
213 rc = 1
214 } else {
215 o = id_cat(out, o, "LIVE-MATCHES-NOTHING -- STOP. The running bytes match NO build, NO .prev and NO banked variant. This is the signature of a HALF-APPLIED deploy or rollback (a FETCH-FAIL/503 that actually succeeded). Every conclusion drawn from this binary's behaviour is unsound until provenance is re-established.\n" as *u8)
216 rc = 4
217 }
218 }
219 }
220 }
221 sys_write(1, out, o)
222 return rc
223}