nx_takedown.nx source
↩ module page · 111 lines · 6277 B
1// nx_takedown.nx -- WRITING/HOSTING arc, rung W-TD-1: NOTICE-AND-TAKEDOWN, the SAFE-HARBOUR POSTURE.
2//
3// ★★★★★★THIRD OPERATOR CORRECTION, 2026-08-04, and it moved the compliance work to a different
4// place entirely: "how it works really is like the dmca takedown -- i don't act as the arbiter of
5// the content and inherit that legal headache, but like google or bing or ai companies i use what
6// is available till its requested to be removed, and i inherit that different set of requirements."
7//
8// THIS IS THE CORRECT ARCHITECTURE AND MY EARLIER ONE WAS BACKWARDS. I had been building a
9// PRE-PUBLICATION ARBITER. In US law that posture is not merely unhelpful, it is often WORSE:
10// * Editorial screening is what turns a conduit into a PUBLISHER, and publishers answer for what
11// they let through. The safe harbours (DMCA 512, and 230 for third-party content) are built for
12// intermediaries who do NOT sit in judgement of every item.
13// * ★★★★★★ACTUAL KNOWLEDGE IS THE ENEMY OF SAFE HARBOUR. 512(c) protection turns on the absence
14// of actual or "red flag" knowledge. A detector that concludes "this is probably unlawful" and
15// proceeds anyway MANUFACTURES the very knowledge that removes the protection. So an aggressive
16// pre-screen can strictly increase exposure. That is the deep reason the operator is right.
17// ⇒ THE DUTY THAT ACTUALLY BINDS IS RESPONSE, NOT PRIOR RESTRAINT: a reachable notice path,
18// expeditious removal on a VALID notice, honest records, and a repeat-infringer policy (512(i)).
19//
20// ⛔THE ONE CLASS THAT IS NOT A TAKEDOWN AT ALL: CSAM. There is an affirmative REPORT-AND-PRESERVE
21// duty (18 U.S.C. 2258A, reporting to NCMEC), and quietly deleting it is not compliance -- it
22// destroys evidence. It gets its own branch and can never be answered with "removed, case closed".
23//
24// ⚠NOT LEGAL ADVICE. This encodes the SHAPE of the regime so a machine can route and a human can
25// answer; it does not decide anyone's case, and where the law is unsettled it says so.
26//
27// Pure integer, NO syscalls, caller owns every buffer.
28// license_tier: ORIGINAL
29// module: nishi-core.hosting.takedown
30// capability: HOSTING_NOTICE_AND_TAKEDOWN
31
32// claim classes
33const TD_COPYRIGHT: i64 = 0 // DMCA 512: counter-notice + restoration exists
34const TD_NCII: i64 = 1 // TAKE IT DOWN Act: 48h removal duty, no casual restoration
35const TD_DEFAMATION: i64 = 2 // truth/harm are for a human (often a court), not a string match
36const TD_PUBLICITY: i64 = 3 // right of publicity, a state-varying tort
37const TD_CSAM: i64 = 4 // NOT a takedown -- preserve + report
38
39// actions
40const TD_REJECT_INCOMPLETE: i64 = 0 // notice missing required elements -> do NOT act on it
41const TD_REMOVE: i64 = 1 // expeditious removal (soft-delete: rule 13, history is sacred)
42const TD_REVIEW_HUMAN: i64 = 2 // genuinely contested -> a person decides
43const TD_PRESERVE_REPORT: i64 = 3 // CSAM: preserve evidence + mandatory report. NEVER silent delete.
44
45// statutory clocks (hours). -1 = "expeditious", deliberately not a fabricated number.
46const TD_HOURS_NCII: i64 = 48
47const TD_HOURS_EXPEDITIOUS: i64 = 0 - 1
48
49// 512(i) repeat-infringer policy: a threshold that EXISTS is the requirement; the number is policy.
50const TD_REPEAT_DEFAULT: i64 = 3
51
52// A notice must carry its required elements before anyone acts on it. Acting on a defective notice
53// is its own exposure -- the target can sue over a wrongful takedown -- so incompleteness is a
54// REFUSAL TO ACT, not a reason to remove "just in case".
55// ★FAIL-CLOSED IN THE DIRECTION THAT PROTECTS BOTH PARTIES: no removal AND no silent discard;
56// the caller is expected to write back asking for the missing element.
57func td_notice_valid(has_work: i64, has_locator: i64, has_contact: i64,
58 has_goodfaith: i64, has_signature: i64) -> i64 {
59 if has_work != 1 { return 0 }
60 if has_locator != 1 { return 0 }
61 if has_contact != 1 { return 0 }
62 if has_goodfaith != 1 { return 0 }
63 if has_signature != 1 { return 0 }
64 return 1
65}
66
67// the clock for a class. NCII is a real statutory number; copyright is "expeditious" and we refuse
68// to invent a figure for it (★WHEN NO NUMBER IS ENACTED, DO NOT MANUFACTURE ONE).
69func td_deadline_hours(class: i64) -> i64 {
70 if class == TD_NCII { return TD_HOURS_NCII }
71 return TD_HOURS_EXPEDITIOUS
72}
73
74// is this notice past its statutory clock? -1 deadline (expeditious) can never be "overdue" by a
75// number, so it reports 0 here and is escalated by policy, not by arithmetic.
76func td_overdue(class: i64, age_hours: i64) -> i64 {
77 let d: i64 = td_deadline_hours(class)
78 if d < 0 { return 0 }
79 if age_hours > d { return 1 }
80 return 0
81}
82
83// THE ROUTING DECISION.
84// ORDER IS THE ARGUMENT, most-absolute first:
85// 1. CSAM -> preserve + report, regardless of notice completeness. A defective notice does
86// not make the duty go away, and removal alone would destroy evidence.
87// 2. invalid -> refuse to act (and answer the sender). Never remove on a defective notice.
88// 3. NCII -> remove. The statute's element is non-consent, and the notice asserts it.
89// 4. copyright -> remove; the counter-notice path is what protects the uploader.
90// 5. the rest -> a human decides. Defamation and publicity turn on facts a host cannot find.
91func td_action(class: i64, valid: i64) -> i64 {
92 if class == TD_CSAM { return TD_PRESERVE_REPORT }
93 if valid != 1 { return TD_REJECT_INCOMPLETE }
94 if class == TD_NCII { return TD_REMOVE }
95 if class == TD_COPYRIGHT { return TD_REMOVE }
96 return TD_REVIEW_HUMAN
97}
98
99// Counter-notice / restoration. DMCA gives the uploader this path; NCII does not get a casual
100// restoration, and CSAM never does. ★A RESTORATION PATH THAT IGNORES THE CLASS IS A LIABILITY.
101func td_restorable(class: i64) -> i64 {
102 if class == TD_COPYRIGHT { return 1 }
103 return 0
104}
105
106// 512(i): terminating repeat infringers "in appropriate circumstances". The POLICY EXISTING and
107// being applied is the requirement; the threshold is the operator's, passed in.
108func td_repeat_action(strikes: i64, threshold: i64) -> i64 {
109 if strikes >= threshold { return 1 }
110 return 0
111}