nx_hunt_evidence.nx source
↩ module page · 117 lines · 3930 B
1// nx_hunt_evidence.nx -- content-addressed kill receipts.
2//
3// Per [[feedback-hunter-gatherer-meta-primitives-outward-inward-axes]]:
4// "nx_hunt_evidence (content-addressed per
5// [[feedback-end-to-end-bit-traceability-architecture]])." When
6// nx_hunter records a KILL, the evidence backing the kill (e.g.,
7// the bug-fix commit hash, the EXCEED-axis benchmark output, the
8// threat-hardening test fixture, the cardinal-text absorbed) is
9// captured as a content-addressed receipt so the kill can be audited
10// later.
11//
12// Composes:
13// nx_hunter -- kills point to evidence rows
14// nx_provenance_chain -- evidence rows chain-link
15// nx_methyl -- each evidence row signed
16// nx_pollinate -- evidence shareable with community
17
18import "nx_syscalls.nx"
19import "nx_tier.nx"
20import "nx_hunter.nx"
21
22const NX_HEV_OK: nx_int = 0
23const NX_HEV_ERR_FULL: nx_int = 1
24const NX_HEV_ERR_NOT_FOUND: nx_int = 2
25
26// ===== Sealed enum: NxEvidenceKind =================================
27
28const NX_EK_COMMIT_HASH: nx_int = 0 // bug-fix commit
29const NX_EK_BENCHMARK_OUTPUT: nx_int = 1 // EXCEED-axis measurement
30const NX_EK_TEST_FIXTURE: nx_int = 2 // threat-hardening test
31const NX_EK_CARDINAL_TEXT: nx_int = 3 // cardinal absorbed
32const NX_EK_FORENSIC_RECORD: nx_int = 4 // signed xenocell observation
33const NX_EK_N_KINDS: nx_int = 5
34
35// ===== Struct: NxHuntEvidence ======================================
36
37struct NxHuntEvidence {
38 evidence_id: nx_int,
39 target_id: nx_int, // points to NxHuntTarget
40 kind: nx_int,
41 content_hash: nx_size,
42 captured_us: nx_size,
43 kill_pillar: nx_int, // mirrors target.kill_pillar
44}
45
46struct NxHuntEvidenceLog {
47 rows: *NxHuntEvidence,
48 capacity: nx_size,
49 count: nx_size,
50}
51
52const NX_HEV_ROW_BYTES: nx_size = 40
53
54func nx_ek_is_valid(k: nx_int) -> nx_int {
55 if k < 0 { return 0 }
56 if k >= NX_EK_N_KINDS { return 0 }
57 return 1
58}
59
60func nx_hunt_evidence_log_new(capacity: nx_size) -> *NxHuntEvidenceLog {
61 let l: *NxHuntEvidenceLog = (sys_mmap(24)) as *NxHuntEvidenceLog
62 let bytes: nx_size = capacity * NX_HEV_ROW_BYTES
63 l.rows = (sys_mmap(bytes)) as *NxHuntEvidence
64 l.capacity = capacity
65 l.count = 0
66 return l
67}
68
69func _hev_at(l: *NxHuntEvidenceLog, idx: nx_size) -> *NxHuntEvidence {
70 return (l.rows as i64 + (idx as i64) * NX_HEV_ROW_BYTES) as *NxHuntEvidence
71}
72
73func nx_hunt_evidence_record(l: *NxHuntEvidenceLog,
74 evidence_id: nx_int,
75 target_id: nx_int,
76 kind: nx_int,
77 content_hash: nx_size,
78 kill_pillar: nx_int,
79 now_us: nx_size) -> nx_int {
80 if nx_ek_is_valid(kind) == 0 { return NX_HEV_ERR_NOT_FOUND }
81 if l.count >= l.capacity { return NX_HEV_ERR_FULL }
82 let r: *NxHuntEvidence = _hev_at(l, l.count)
83 r.evidence_id = evidence_id
84 r.target_id = target_id
85 r.kind = kind
86 r.content_hash = content_hash
87 r.captured_us = now_us
88 r.kill_pillar = kill_pillar
89 l.count = l.count + 1
90 return NX_HEV_OK
91}
92
93func nx_hunt_evidence_count_for_target(l: *NxHuntEvidenceLog, target_id: nx_int) -> nx_int {
94 var hits: nx_int = 0
95 var i: nx_size = 0
96 while i < l.count {
97 let r: *NxHuntEvidence = _hev_at(l, i)
98 if r.target_id == target_id { hits = hits + 1 }
99 i = i + 1
100 }
101 return hits
102}
103
104func nx_hunt_evidence_count_by_kind(l: *NxHuntEvidenceLog, kind: nx_int) -> nx_int {
105 var hits: nx_int = 0
106 var i: nx_size = 0
107 while i < l.count {
108 let r: *NxHuntEvidence = _hev_at(l, i)
109 if r.kind == kind { hits = hits + 1 }
110 i = i + 1
111 }
112 return hits
113}
114
115func nx_hunt_evidence_count(l: *NxHuntEvidenceLog) -> nx_size {
116 return l.count
117}