code wiki / (root) / nx_covenant.nx

nx_covenant.nx source

↩ module page · 251 lines · 9291 B

1// nx_covenant.nx -- multi-stakeholder + multi-generational consent. 2// 3// Per META-CARDINAL feedback-regenerative-stewardship-doctrine-captain-moroni: 4// the legal-and-relational substrate where regenerative intentions become 5// regenerative actions without harm. Composes: landowner consent + 6// Indigenous Free Prior and Informed Consent (FPIC) per UN Declaration 7// on the Rights of Indigenous Peoples + Indigenous Data Sovereignty + 8// CARE Principles + watershed rights + regulatory compliance + neighbor 9// relationships + future-inheritor obligations. 10// 11// V1 ships sealed enums of stakeholder classes + consent states + 12// covenant lifecycle + revocation handling. Per [[feedback-user-owns- 13// every-bit]]: every consent is operator-scope-bounded + time-bounded 14// + revocable. 15 16import "nx_syscalls.nx" 17import "nx_tier.nx" 18 19// ===== Sealed enum: NxStakeholderClass ============================ 20// 21// Per regenerative-stewardship roadmap ยง2.8 -- the canonical stakeholder 22// classes the substrate recognizes for multi-stakeholder consent. 23 24const NX_SH_LANDOWNER: nx_int = 0 25const NX_SH_INDIGENOUS_NATION: nx_int = 1 // requires FPIC 26const NX_SH_DOWNSTREAM_WATER_USER: nx_int = 2 27const NX_SH_REGULATORY_BODY: nx_int = 3 28const NX_SH_NEIGHBOR: nx_int = 4 29const NX_SH_FUTURE_INHERITOR: nx_int = 5 // multi-generational 30const NX_SH_OPERATOR: nx_int = 6 // the primary actor 31const NX_SH_FAMILY_MEMBER: nx_int = 7 32const NX_SH_COMMUNITY_COUNCIL: nx_int = 8 33const NX_SH_TRUSTED_ADVISOR: nx_int = 9 // counsel / ecologist / etc. 34const NX_SH_N_CLASSES: nx_int = 10 35 36// ===== Sealed enum: NxConsentState ================================ 37 38const NX_CN_PENDING: nx_int = 0 39const NX_CN_GRANTED: nx_int = 1 40const NX_CN_GRANTED_CONDITIONAL: nx_int = 2 // with stipulations 41const NX_CN_DECLINED: nx_int = 3 42const NX_CN_REVOKED: nx_int = 4 43const NX_CN_EXPIRED: nx_int = 5 44const NX_CN_NOT_APPLICABLE: nx_int = 6 // stakeholder doesn't apply here 45const NX_CN_N_STATES: nx_int = 7 46 47// ===== Sealed enum: NxCovenantVerdict ============================= 48 49const NX_CV_V_OK_ALL_GRANTED: nx_int = 0 50const NX_CV_V_PENDING_STAKEHOLDERS: nx_int = 1 51const NX_CV_V_BLOCKED_DECLINED: nx_int = 2 52const NX_CV_V_FPIC_REQUIRED_MISSING: nx_int = 3 // Indigenous consent missing 53const NX_CV_V_REVOKED: nx_int = 4 54const NX_CV_V_EXPIRED: nx_int = 5 55const NX_CV_V_NULL: nx_int = 6 56const NX_CV_V_INVALID: nx_int = 7 57const NX_CV_V_N: nx_int = 8 58 59// ===== Struct: NxConsentEntry ===================================== 60 61struct NxConsentEntry { 62 stakeholder_id: nx_int, 63 stakeholder_class: nx_int, 64 state: nx_int, 65 granted_at_us: nx_size, 66 expires_at_us: nx_size, 67 revoked_at_us: nx_size, 68 conditions_hash: nx_size, 69} 70 71const NX_CN_ENT_BYTES: nx_int = 48 72 73// ===== Struct: NxCovenant ========================================= 74 75struct NxCovenant { 76 covenant_id: nx_int, 77 project_hash: nx_size, 78 entries: *u8, // array of NxConsentEntry 79 n_entries: nx_int, 80 capacity: nx_int, 81 requires_fpic: nx_int, // 1 if ancestral territory 82 operator_initiated_us: nx_size, 83} 84 85const NX_CV_BYTES: nx_int = 48 86 87func nx_sh_class_is_valid(c: nx_int) -> nx_int { 88 if c < 0 { return 0 } 89 if c >= NX_SH_N_CLASSES { return 0 } 90 return 1 91} 92 93func nx_cn_state_is_valid(s: nx_int) -> nx_int { 94 if s < 0 { return 0 } 95 if s >= NX_CN_N_STATES { return 0 } 96 return 1 97} 98 99func nx_cv_v_is_valid(v: nx_int) -> nx_int { 100 if v < 0 { return 0 } 101 if v >= NX_CV_V_N { return 0 } 102 return 1 103} 104 105func nx_cn_state_is_blocking(s: nx_int) -> nx_int { 106 if s == NX_CN_DECLINED { return 1 } 107 if s == NX_CN_REVOKED { return 1 } 108 if s == NX_CN_EXPIRED { return 1 } 109 return 0 110} 111 112func nx_cn_state_is_satisfied(s: nx_int) -> nx_int { 113 if s == NX_CN_GRANTED { return 1 } 114 if s == NX_CN_GRANTED_CONDITIONAL { return 1 } 115 if s == NX_CN_NOT_APPLICABLE { return 1 } 116 return 0 117} 118 119func nx_sh_class_requires_fpic(c: nx_int) -> nx_int { 120 if c == NX_SH_INDIGENOUS_NATION { return 1 } 121 return 0 122} 123 124func nx_cv_new(covenant_id: nx_int, 125 project_hash: nx_size, 126 capacity: nx_int, 127 requires_fpic: nx_int, 128 now_us: nx_size) -> *NxCovenant { 129 if capacity <= 0 { return 0 as *NxCovenant } 130 let raw: *u8 = sys_mmap(NX_CV_BYTES) 131 let c: *NxCovenant = raw as *NxCovenant 132 c.covenant_id = covenant_id 133 c.project_hash = project_hash 134 c.entries = sys_mmap(capacity * NX_CN_ENT_BYTES) 135 c.n_entries = 0 136 c.capacity = capacity 137 c.requires_fpic = requires_fpic 138 c.operator_initiated_us = now_us 139 return c 140} 141 142func _cv_entry_at(c: *NxCovenant, idx: nx_int) -> *NxConsentEntry { 143 if idx < 0 { return 0 as *NxConsentEntry } 144 if idx >= c.n_entries { return 0 as *NxConsentEntry } 145 let off: nx_int = idx * NX_CN_ENT_BYTES 146 return (c.entries + off) as *NxConsentEntry 147} 148 149func nx_cv_add_stakeholder(c: *NxCovenant, 150 stakeholder_id: nx_int, 151 stakeholder_class: nx_int, 152 now_us: nx_size) -> nx_int { 153 if (c as i64) == 0 { return NX_CV_V_NULL } 154 if nx_sh_class_is_valid(stakeholder_class) == 0 { return NX_CV_V_INVALID } 155 if c.n_entries >= c.capacity { return NX_CV_V_INVALID } 156 let off: nx_int = c.n_entries * NX_CN_ENT_BYTES 157 let e: *NxConsentEntry = (c.entries + off) as *NxConsentEntry 158 e.stakeholder_id = stakeholder_id 159 e.stakeholder_class = stakeholder_class 160 e.state = NX_CN_PENDING 161 e.granted_at_us = 0 162 e.expires_at_us = 0 163 e.revoked_at_us = 0 164 e.conditions_hash = 0 165 c.n_entries = c.n_entries + 1 166 return NX_CV_V_OK_ALL_GRANTED 167} 168 169func nx_cv_set_consent(c: *NxCovenant, 170 stakeholder_id: nx_int, 171 state: nx_int, 172 conditions_hash: nx_size, 173 lifetime_ms: nx_int, 174 now_us: nx_size) -> nx_int { 175 if (c as i64) == 0 { return NX_CV_V_NULL } 176 if nx_cn_state_is_valid(state) == 0 { return NX_CV_V_INVALID } 177 var i: nx_int = 0 178 while i < c.n_entries { 179 let e: *NxConsentEntry = _cv_entry_at(c, i) 180 if e.stakeholder_id == stakeholder_id { 181 e.state = state 182 if state == NX_CN_GRANTED { 183 e.granted_at_us = now_us 184 e.expires_at_us = now_us + (lifetime_ms as nx_size) * 1000 185 } 186 if state == NX_CN_GRANTED_CONDITIONAL { 187 e.granted_at_us = now_us 188 e.expires_at_us = now_us + (lifetime_ms as nx_size) * 1000 189 e.conditions_hash = conditions_hash 190 } 191 if state == NX_CN_REVOKED { e.revoked_at_us = now_us } 192 return NX_CV_V_OK_ALL_GRANTED 193 } 194 i = i + 1 195 } 196 return NX_CV_V_INVALID // stakeholder not registered 197} 198 199func nx_cv_classify(c: *NxCovenant, now_us: nx_size) -> nx_int { 200 if (c as i64) == 0 { return NX_CV_V_NULL } 201 // Check FPIC requirement first 202 if c.requires_fpic == 1 { 203 var found_indigenous: nx_int = 0 204 var found_indigenous_grant: nx_int = 0 205 var i: nx_int = 0 206 while i < c.n_entries { 207 let e: *NxConsentEntry = _cv_entry_at(c, i) 208 if e.stakeholder_class == NX_SH_INDIGENOUS_NATION { 209 found_indigenous = 1 210 if nx_cn_state_is_satisfied(e.state) == 1 { 211 found_indigenous_grant = 1 212 } 213 } 214 i = i + 1 215 } 216 if found_indigenous == 0 { return NX_CV_V_FPIC_REQUIRED_MISSING } 217 if found_indigenous_grant == 0 { return NX_CV_V_FPIC_REQUIRED_MISSING } 218 } 219 // Walk all entries for blocking states 220 var any_pending: nx_int = 0 221 var j: nx_int = 0 222 while j < c.n_entries { 223 let e: *NxConsentEntry = _cv_entry_at(c, j) 224 if e.state == NX_CN_GRANTED { 225 if e.expires_at_us > 0 { 226 if now_us > e.expires_at_us { 227 e.state = NX_CN_EXPIRED 228 } 229 } 230 } 231 if e.state == NX_CN_REVOKED { return NX_CV_V_REVOKED } 232 if e.state == NX_CN_DECLINED { return NX_CV_V_BLOCKED_DECLINED } 233 if e.state == NX_CN_EXPIRED { return NX_CV_V_EXPIRED } 234 if e.state == NX_CN_PENDING { any_pending = 1 } 235 j = j + 1 236 } 237 if any_pending == 1 { return NX_CV_V_PENDING_STAKEHOLDERS } 238 return NX_CV_V_OK_ALL_GRANTED 239} 240 241func nx_cv_count_by_class(c: *NxCovenant, class_id: nx_int) -> nx_int { 242 if (c as i64) == 0 { return 0 } 243 var count: nx_int = 0 244 var i: nx_int = 0 245 while i < c.n_entries { 246 let e: *NxConsentEntry = _cv_entry_at(c, i) 247 if e.stakeholder_class == class_id { count = count + 1 } 248 i = i + 1 249 } 250 return count 251}