nx_book.nx source
↩ module page · 208 lines · 6740 B
1// nx_book.nx -- family ledger / operator-visible log.
2//
3// Per [[feedback-captain-moroni-doctrine]]: "All bypass events logged
4// in books. Audit trail accessible to family." THE canonical
5// operator-visible append-only ledger. Distinct from internal-detail
6// logs (nx_evict_journal / nx_provenance_chain) which are forensic;
7// nx_book is the human-readable, family-facing audit trail.
8//
9// Per [[feedback-self-surfacing-intelligence-staged-autonomy]]: when
10// the substrate takes any significant action (twin-key authorized,
11// drone deployed, sanctuary opened, reclaim applied, failover
12// executed), the BOOK records it loud + structured so the family
13// reviewer can read what happened without grep'ing 47 JSONL files.
14//
15// Composes:
16// nx_twin_key -- every twin-key authorization writes a book row
17// nx_drone_doctrine -- every drone session deployment writes a row
18// nx_transponder_quiescence -- every emergency_override writes a row
19// nx_reclaim -- every reclamation safety envelope writes a row
20// nx_promote -- every failover writes a row
21// nx_xenocell -- xenocell intrusion events write a row
22// nx_ai_audit -- every BLOCKED AI proposal writes a row
23// nx_scam_detector -- every CONFIRMED_PATTERN scam writes a row
24
25import "nx_syscalls.nx"
26import "nx_tier.nx"
27
28// ===== Sealed enum: NxBookEntryKind ===============================
29
30const NX_BK_TWIN_KEY_AUTHORIZED: nx_int = 0
31const NX_BK_DRONE_DEPLOYED: nx_int = 1
32const NX_BK_SANCTUARY_OPENED: nx_int = 2
33const NX_BK_RECLAIM_APPLIED: nx_int = 3
34const NX_BK_FAILOVER_EXECUTED: nx_int = 4
35const NX_BK_XENO_ALERT: nx_int = 5
36const NX_BK_SCAM_FLAGGED: nx_int = 6
37const NX_BK_AI_PROPOSAL_BLOCKED: nx_int = 7
38const NX_BK_TREATY_BREACHED: nx_int = 8
39const NX_BK_TRACE_SHARED: nx_int = 9
40const NX_BK_OPERATOR_OVERRIDE: nx_int = 10
41const NX_BK_HEALTH_RED_TRIGGERED: nx_int = 11
42const NX_BK_N_KINDS: nx_int = 12
43
44// ===== Sealed enum: NxBookSeverity ================================
45
46const NX_BS_INFO: nx_int = 0
47const NX_BS_NOTICE: nx_int = 1
48const NX_BS_WARNING: nx_int = 2
49const NX_BS_ALERT: nx_int = 3
50const NX_BS_N_SEVS: nx_int = 4
51
52const NX_BK_OK: nx_int = 0
53const NX_BK_ERR_FULL: nx_int = 1
54const NX_BK_ERR_BAD_KIND: nx_int = 2
55
56// ===== Struct: NxBookEntry ========================================
57
58struct NxBookEntry {
59 entry_id: nx_int,
60 ts_us: nx_size,
61 kind: nx_int,
62 severity: nx_int,
63 subject_id: nx_int, // cell_id / pid / request_id
64 payload_hash: nx_size,
65 seen_by_family: nx_int, // 1 once family member reviewed
66}
67
68struct NxBook {
69 entries: *NxBookEntry,
70 capacity: nx_size,
71 count: nx_size,
72}
73
74const NX_BK_ENTRY_BYTES: nx_size = 56
75
76func nx_bk_kind_is_valid(k: nx_int) -> nx_int {
77 if k < 0 { return 0 }
78 if k >= NX_BK_N_KINDS { return 0 }
79 return 1
80}
81
82func nx_bk_severity_is_valid(s: nx_int) -> nx_int {
83 if s < 0 { return 0 }
84 if s >= NX_BS_N_SEVS { return 0 }
85 return 1
86}
87
88func nx_book_new(capacity: nx_size) -> *NxBook {
89 let b: *NxBook = (sys_mmap(24)) as *NxBook
90 let bytes: nx_size = capacity * NX_BK_ENTRY_BYTES
91 b.entries = (sys_mmap(bytes)) as *NxBookEntry
92 b.capacity = capacity
93 b.count = 0
94 return b
95}
96
97func _bk_at(b: *NxBook, idx: nx_size) -> *NxBookEntry {
98 return (b.entries as i64 + (idx as i64) * NX_BK_ENTRY_BYTES) as *NxBookEntry
99}
100
101// ===== nx_book_record =============================================
102//
103// Append one entry. severity defaults to caller's choice; ts_us is
104// monotonic. payload_hash references any detail in nx_provenance_chain
105// or nx_evict_journal that backs this book entry.
106
107func nx_book_record(b: *NxBook,
108 entry_id: nx_int,
109 ts_us: nx_size,
110 kind: nx_int,
111 severity: nx_int,
112 subject_id: nx_int,
113 payload_hash: nx_size) -> nx_int {
114 if nx_bk_kind_is_valid(kind) == 0 { return NX_BK_ERR_BAD_KIND }
115 if nx_bk_severity_is_valid(severity) == 0 { return NX_BK_ERR_BAD_KIND }
116 if b.count >= b.capacity { return NX_BK_ERR_FULL }
117 let e: *NxBookEntry = _bk_at(b, b.count)
118 e.entry_id = entry_id
119 e.ts_us = ts_us
120 e.kind = kind
121 e.severity = severity
122 e.subject_id = subject_id
123 e.payload_hash = payload_hash
124 e.seen_by_family = 0
125 b.count = b.count + 1
126 return NX_BK_OK
127}
128
129func _bk_find(b: *NxBook, entry_id: nx_int) -> nx_int {
130 var i: nx_size = 0
131 while i < b.count {
132 let e: *NxBookEntry = _bk_at(b, i)
133 if e.entry_id == entry_id { return i as i64 }
134 i = i + 1
135 }
136 return -1
137}
138
139// ===== nx_book_mark_seen ==========================================
140//
141// Family reviewer marks an entry as seen. Critical for audit-trail
142// integrity: substrate distinguishes "logged" from "reviewed."
143
144func nx_book_mark_seen(b: *NxBook, entry_id: nx_int) -> nx_int {
145 let idx: nx_int = _bk_find(b, entry_id)
146 if idx < 0 { return NX_BK_ERR_BAD_KIND }
147 let e: *NxBookEntry = _bk_at(b, idx as nx_size)
148 e.seen_by_family = 1
149 return NX_BK_OK
150}
151
152// ===== nx_book_count_unseen =======================================
153
154func nx_book_count_unseen(b: *NxBook) -> nx_int {
155 var hits: nx_int = 0
156 var i: nx_size = 0
157 while i < b.count {
158 let e: *NxBookEntry = _bk_at(b, i)
159 if e.seen_by_family == 0 { hits = hits + 1 }
160 i = i + 1
161 }
162 return hits
163}
164
165func nx_book_count(b: *NxBook) -> nx_size {
166 return b.count
167}
168
169func nx_book_count_by_kind(b: *NxBook, kind: nx_int) -> nx_int {
170 var hits: nx_int = 0
171 var i: nx_size = 0
172 while i < b.count {
173 let e: *NxBookEntry = _bk_at(b, i)
174 if e.kind == kind { hits = hits + 1 }
175 i = i + 1
176 }
177 return hits
178}
179
180func nx_book_count_by_severity(b: *NxBook, severity: nx_int) -> nx_int {
181 var hits: nx_int = 0
182 var i: nx_size = 0
183 while i < b.count {
184 let e: *NxBookEntry = _bk_at(b, i)
185 if e.severity == severity { hits = hits + 1 }
186 i = i + 1
187 }
188 return hits
189}
190
191// ===== nx_book_count_alerts_unseen =================================
192//
193// Predicate-friendly query: how many ALERT-severity entries does
194// the family still need to review? > 0 means substrate is asking
195// for attention.
196
197func nx_book_count_alerts_unseen(b: *NxBook) -> nx_int {
198 var hits: nx_int = 0
199 var i: nx_size = 0
200 while i < b.count {
201 let e: *NxBookEntry = _bk_at(b, i)
202 if e.severity == NX_BS_ALERT {
203 if e.seen_by_family == 0 { hits = hits + 1 }
204 }
205 i = i + 1
206 }
207 return hits
208}