nx_redact_lib.nx source
↩ module page · 112 lines · 4497 B
1// nx_redact_lib.nx -- REDACTION COMPLETENESS verifier for e-discovery production. Deterministic, byte-exact.
2//
3// The content-level companion to nx_ediscovery (which is the ALLOW-LIST: only affirmatively-reviewed,
4// responsive documents may be produced). This is the other half: even a responsive document must have its
5// sensitive content redacted before it leaves the door. Where mainstream PII tools FLAG a hit for a human to
6// eyeball, this is FAIL-CLOSED -- a document is not producible while any detectable SSN or privilege marker
7// remains, full stop. Deterministic byte scanning, no LLM, no probability.
8//
9// The SSN detector is PRECISE, not greedy: it matches ddd-dd-dddd only at a real number boundary, so it does
10// NOT false-fire on a wrong grouping (dd-dd-dddd) or on an SSN-shaped run embedded in a longer digit string
11// (over-blocking a clean doc is safe but annoying; the boundary checks keep it honest). Missing a real SSN
12// (a false NEGATIVE) is the dangerous case and is what the byte-exact pattern forecloses.
13//
14// SCALE ENVELOPE (declared): substring is naive O(len*needle); KMP is the speed rung for large productions.
15// license_tier: ORIGINAL No hw writes (Rule 26). LIB.
16
17const REDACT_NOT_FOUND: i64 = 0 - 1
18
19func redact_len(s: *u8) -> i64 {
20 var n: i64 = 0
21 while s[n] != (0 as u8) { n = n + 1 }
22 return n
23}
24
25func redact_is_digit(c: u8) -> i64 {
26 if (c as i64) < 48 { return 0 }
27 if (c as i64) > 57 { return 0 }
28 return 1
29}
30
31// is there a precise SSN (ddd-dd-dddd) starting at index i, at a non-digit boundary on both sides?
32func redact_is_ssn_at(doc: *u8, i: i64, len: i64) -> i64 {
33 if i + 11 > len { return 0 }
34 if i > 0 {
35 if redact_is_digit(doc[i - 1]) == 1 { return 0 }
36 }
37 if redact_is_digit(doc[i]) == 0 { return 0 }
38 if redact_is_digit(doc[i + 1]) == 0 { return 0 }
39 if redact_is_digit(doc[i + 2]) == 0 { return 0 }
40 if doc[i + 3] != (45 as u8) { return 0 }
41 if redact_is_digit(doc[i + 4]) == 0 { return 0 }
42 if redact_is_digit(doc[i + 5]) == 0 { return 0 }
43 if doc[i + 6] != (45 as u8) { return 0 }
44 if redact_is_digit(doc[i + 7]) == 0 { return 0 }
45 if redact_is_digit(doc[i + 8]) == 0 { return 0 }
46 if redact_is_digit(doc[i + 9]) == 0 { return 0 }
47 if redact_is_digit(doc[i + 10]) == 0 { return 0 }
48 if i + 11 < len {
49 if redact_is_digit(doc[i + 11]) == 1 { return 0 }
50 }
51 return 1
52}
53
54// first SSN index or REDACT_NOT_FOUND.
55func redact_find_ssn(doc: *u8, len: i64) -> i64 {
56 var i: i64 = 0
57 var found: i64 = REDACT_NOT_FOUND
58 while i < len {
59 if found == REDACT_NOT_FOUND {
60 if redact_is_ssn_at(doc, i, len) == 1 { found = i }
61 }
62 i = i + 1
63 }
64 return found
65}
66
67// count of SSN occurrences (non-overlapping by construction of the boundary checks).
68func redact_count_ssn(doc: *u8, len: i64) -> i64 {
69 var i: i64 = 0
70 var c: i64 = 0
71 while i < len {
72 if redact_is_ssn_at(doc, i, len) == 1 { c = c + 1 }
73 i = i + 1
74 }
75 return c
76}
77
78// naive substring: first index of `needle` in `doc`, or REDACT_NOT_FOUND. An empty needle is NOT a match
79// (closes the substring-of-everything hole).
80func redact_contains(doc: *u8, len: i64, needle: *u8, nlen: i64) -> i64 {
81 if nlen == 0 { return REDACT_NOT_FOUND }
82 if nlen > len { return REDACT_NOT_FOUND }
83 var i: i64 = 0
84 var found: i64 = REDACT_NOT_FOUND
85 while i <= len - nlen {
86 if found == REDACT_NOT_FOUND {
87 var j: i64 = 0
88 var hit: i64 = 1
89 while j < nlen {
90 if doc[i + j] != needle[j] { hit = 0 }
91 j = j + 1
92 }
93 if hit == 1 { found = i }
94 }
95 i = i + 1
96 }
97 return found
98}
99
100// *is the document clean enough to leave the door? No SSN AND no privilege marker present.
101func redact_clean_for_production(doc: *u8, len: i64, marker: *u8, mlen: i64) -> i64 {
102 if redact_find_ssn(doc, len) != REDACT_NOT_FOUND { return 0 }
103 if redact_contains(doc, len, marker, mlen) != REDACT_NOT_FOUND { return 0 }
104 return 1
105}
106
107// *FAIL-CLOSED production decision: producible ONLY if the document was reviewed AND is redaction-clean.
108// Either gate alone is insufficient -- an unreviewed clean doc and a reviewed dirty doc are both blocked.
109func redact_production_ok(doc: *u8, len: i64, reviewed: i64, marker: *u8, mlen: i64) -> i64 {
110 if reviewed == 0 { return 0 }
111 return redact_clean_for_production(doc, len, marker, mlen)
112}