code wiki / _hdl_build / nx_connect_presence.nx

nx_connect_presence.nx source

↩ module page · 255 lines · 10035 B

1// nx_connect_presence.nx -- CONNECT: typing indicator + online presence + scheduled/silent send. 2// Closes two MSG cells of nx_connect_func_census (typing+presence; scheduled/silent send). 3// BY CONSTRUCTION properties: 4// - the typing signal is a {conv,user,expiry} triple ONLY -- no draft-text field exists in the 5// schema, and it EXPIRES (ephemeral): presence never becomes a stale lie. NEG-CONTROL: a sticky 6// no-TTL incumbent model still claims "typing" an hour later; ours has expired. 7// - last-seen privacy is the USER's setting: a coarse-mode profile renders only a "recently" 8// bucket, never the exact timestamp (data minimization at render time). 9// - scheduled send delivers exactly AT/after the due tick, never early; SILENT send delivers with 10// ZERO notification events (Telegram-class silent send); the delivery tick is IDEMPOTENT 11// (rule 10: a re-run tick cannot double-send). 12// Times are passed in (deterministic, no clock). 100% sovereign. license_tier: ORIGINAL expect_exit: 0 13import "nx_syscalls.nx" 14const PR_MAGIC_4600: i64 = 4600 15const PR_MAGIC_2000: i64 = 2000 16const PR_MAGIC_1999: i64 = 1999 17const PR_MAGIC_2100: i64 = 2100 18 19const PR_MAX: i64 = 16 20const TY_MAX: i64 = 32 21const SC_MAX: i64 = 16 22const TY_TTL: i64 = 5 23 24const CX_PRU: i64 = 0 25const CX_PRST: i64 = 1 26const CX_PRLAST: i64 = 2 27const CX_PRCOARSE: i64 = 3 28const CX_NPR: i64 = 4 29const CX_TYC: i64 = 5 30const CX_TYU: i64 = 6 31const CX_TYX: i64 = 7 32const CX_NTY: i64 = 8 33const CX_SCDUE: i64 = 9 34const CX_SCSIL: i64 = 10 35const CX_SCSENT: i64 = 11 36const CX_NSC: i64 = 12 37const CX_DELIV: i64 = 13 38const CX_NOTIF: i64 = 14 39 40func sw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 41func sn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 } 42func tcheck(pass: i64, label: *u8, fails: *i64) -> i64 { 43 sw(" " as *u8); sw(label); sw(": " as *u8) 44 if pass==1 { sw("PASS\n" as *u8) } else { sw("FAIL\n" as *u8); fails[0]=fails[0]+1 } 45 return 0 46} 47func cxp(ctx: *i64, i: i64) -> *i64 { return ctx[i] as *i64 } 48 49func pr_idx(ctx: *i64, user: i64) -> i64 { 50 let pu: *i64 = cxp(ctx, CX_PRU) 51 let np: *i64 = cxp(ctx, CX_NPR) 52 var i: i64=0 53 while i<np[0] { if pu[i]==user { return i } i=i+1 } 54 return 0-1 55} 56func pr_set(ctx: *i64, user: i64, state: i64, now: i64) -> i64 { 57 var i: i64 = pr_idx(ctx, user) 58 let pu: *i64 = cxp(ctx, CX_PRU) 59 let ps: *i64 = cxp(ctx, CX_PRST) 60 let pl: *i64 = cxp(ctx, CX_PRLAST) 61 let np: *i64 = cxp(ctx, CX_NPR) 62 if i<0 { i=np[0]; pu[i]=user; np[0]=i+1 } 63 ps[i]=state 64 pl[i]=now 65 return i 66} 67// viewer render: 0 offline-exact 1 online 2 away 3 offline-coarse("recently"). -1 unknown user. 68func pr_view(ctx: *i64, target: i64, now: i64) -> i64 { 69 let i: i64 = pr_idx(ctx, target) 70 if i<0 { return 0-1 } 71 let ps: *i64 = cxp(ctx, CX_PRST) 72 let pc: *i64 = cxp(ctx, CX_PRCOARSE) 73 if ps[i]==1 { return 1 } 74 if ps[i]==2 { return 2 } 75 if pc[i]==1 { return 3 } 76 return 0 77} 78// exact last_seen ONLY for a non-coarse profile; coarse -> -1 (the exact number never leaves) 79func pr_last_seen(ctx: *i64, target: i64) -> i64 { 80 let i: i64 = pr_idx(ctx, target) 81 if i<0 { return 0-1 } 82 let pc: *i64 = cxp(ctx, CX_PRCOARSE) 83 let pl: *i64 = cxp(ctx, CX_PRLAST) 84 if pc[i]==1 { return 0-1 } 85 return pl[i] 86} 87func ty_set(ctx: *i64, conv: i64, user: i64, now: i64) -> i64 { 88 let tc: *i64 = cxp(ctx, CX_TYC) 89 let tu: *i64 = cxp(ctx, CX_TYU) 90 let tx: *i64 = cxp(ctx, CX_TYX) 91 let nt: *i64 = cxp(ctx, CX_NTY) 92 var i: i64=0 93 while i<nt[0] { 94 if tc[i]==conv { if tu[i]==user { tx[i]=now+TY_TTL; return i } } 95 i=i+1 96 } 97 let k: i64=nt[0] 98 tc[k]=conv; tu[k]=user; tx[k]=now+TY_TTL 99 nt[0]=k+1 100 return k 101} 102// ephemeral: active iff now < expiry. the schema has NO draft-text field at all. 103func ty_active(ctx: *i64, conv: i64, user: i64, now: i64) -> i64 { 104 let tc: *i64 = cxp(ctx, CX_TYC) 105 let tu: *i64 = cxp(ctx, CX_TYU) 106 let tx: *i64 = cxp(ctx, CX_TYX) 107 let nt: *i64 = cxp(ctx, CX_NTY) 108 var i: i64=0 109 while i<nt[0] { 110 if tc[i]==conv { if tu[i]==user { if now<tx[i] { return 1 } return 0 } } 111 i=i+1 112 } 113 return 0 114} 115// NEG-CONTROL incumbent: sticky typing flag with NO expiry -- stale presence forever 116func ty_sticky_active(set_at: i64, now: i64) -> i64 { 117 if now>=set_at { return 1 } 118 return 0 119} 120// schedule a message; delivery via sc_tick. silent=1 -> no notification event on delivery. 121func sc_add(ctx: *i64, due: i64, silent: i64) -> i64 { 122 let sd: *i64 = cxp(ctx, CX_SCDUE) 123 let ss: *i64 = cxp(ctx, CX_SCSIL) 124 let st: *i64 = cxp(ctx, CX_SCSENT) 125 let ns: *i64 = cxp(ctx, CX_NSC) 126 let k: i64=ns[0] 127 sd[k]=due; ss[k]=silent; st[k]=0 128 ns[0]=k+1 129 return k 130} 131// IDEMPOTENT delivery tick: due & unsent -> deliver once; notify unless silent. 132func sc_tick(ctx: *i64, now: i64) -> i64 { 133 let sd: *i64 = cxp(ctx, CX_SCDUE) 134 let ss: *i64 = cxp(ctx, CX_SCSIL) 135 let st: *i64 = cxp(ctx, CX_SCSENT) 136 let ns: *i64 = cxp(ctx, CX_NSC) 137 let dl: *i64 = cxp(ctx, CX_DELIV) 138 let nf: *i64 = cxp(ctx, CX_NOTIF) 139 var sent_now: i64=0 140 var i: i64=0 141 while i<ns[0] { 142 if st[i]==0 { 143 if now>=sd[i] { 144 st[i]=1 145 dl[0]=dl[0]+1 146 if ss[i]==0 { nf[0]=nf[0]+1 } 147 sent_now=sent_now+1 148 } 149 } 150 i=i+1 151 } 152 return sent_now 153} 154 155func main() -> i64 { 156 let fails: *i64 = sys_mmap(16) as *i64 157 fails[0]=0 158 sw("=== nx_connect_presence -- typing + presence + scheduled/silent send ===\n" as *u8) 159 160 let ctx: *i64 = sys_mmap(16*8) as *i64 161 let pr_user: *i64 = sys_mmap(PR_MAX*8) as *i64 162 let pr_state: *i64 = sys_mmap(PR_MAX*8) as *i64 163 let pr_last: *i64 = sys_mmap(PR_MAX*8) as *i64 164 let pr_coarse: *i64 = sys_mmap(PR_MAX*8) as *i64 165 let npr: *i64 = sys_mmap(8) as *i64 166 npr[0]=0 167 let ty_conv: *i64 = sys_mmap(TY_MAX*8) as *i64 168 let ty_user: *i64 = sys_mmap(TY_MAX*8) as *i64 169 let ty_exp: *i64 = sys_mmap(TY_MAX*8) as *i64 170 let nty: *i64 = sys_mmap(8) as *i64 171 nty[0]=0 172 let sc_due: *i64 = sys_mmap(SC_MAX*8) as *i64 173 let sc_sil: *i64 = sys_mmap(SC_MAX*8) as *i64 174 let sc_sent: *i64 = sys_mmap(SC_MAX*8) as *i64 175 let nsc: *i64 = sys_mmap(8) as *i64 176 nsc[0]=0 177 let deliv: *i64 = sys_mmap(8) as *i64 178 deliv[0]=0 179 let notif: *i64 = sys_mmap(8) as *i64 180 notif[0]=0 181 ctx[CX_PRU]=pr_user as i64; ctx[CX_PRST]=pr_state as i64; ctx[CX_PRLAST]=pr_last as i64 182 ctx[CX_PRCOARSE]=pr_coarse as i64; ctx[CX_NPR]=npr as i64 183 ctx[CX_TYC]=ty_conv as i64; ctx[CX_TYU]=ty_user as i64; ctx[CX_TYX]=ty_exp as i64 184 ctx[CX_NTY]=nty as i64 185 ctx[CX_SCDUE]=sc_due as i64; ctx[CX_SCSIL]=sc_sil as i64; ctx[CX_SCSENT]=sc_sent as i64 186 ctx[CX_NSC]=nsc as i64 187 ctx[CX_DELIV]=deliv as i64 188 ctx[CX_NOTIF]=notif as i64 189 190 // T1: presence transitions online -> away -> offline 191 pr_set(ctx, 1, 1, 100) 192 let v1a: i64 = pr_view(ctx, 1, 100) 193 pr_set(ctx, 1, 2, 150) 194 let v1b: i64 = pr_view(ctx, 1, 150) 195 pr_set(ctx, 1, 0, 200) 196 let v1c: i64 = pr_view(ctx, 1, 200) 197 var t1: i64=0 198 if v1a==1 { if v1b==2 { if v1c==0 { t1=1 } } } 199 tcheck(t1, "T1 presence transitions online/away/offline render correctly" as *u8, fails) 200 201 // T2: last-seen privacy -- coarse profile renders bucket only, exact timestamp never leaves 202 pr_set(ctx, 2, 0, 555) 203 let i2: i64 = pr_idx(ctx, 2) 204 pr_coarse[i2]=1 205 let v2: i64 = pr_view(ctx, 2, 600) 206 let ls2: i64 = pr_last_seen(ctx, 2) 207 let ls1: i64 = pr_last_seen(ctx, 1) 208 var t2: i64=0 209 if v2==3 { if ls2==(0-1) { if ls1==200 { t2=1 } } } 210 tcheck(t2, "T2 last-seen privacy: coarse profile leaks NO exact timestamp; exact mode does" as *u8, fails) 211 212 // T3: typing is EPHEMERAL -- active now, expired after TTL 213 ty_set(ctx, 40, 1, 1000) 214 let a3: i64 = ty_active(ctx, 40, 1, 1002) 215 let b3: i64 = ty_active(ctx, 40, 1, 1006) 216 var t3: i64=0 217 if a3==1 { if b3==0 { t3=1 } } 218 tcheck(t3, "T3 typing indicator ephemeral: active in-window, expired after TTL" as *u8, fails) 219 220 // T4: NEG-CONTROL sticky incumbent still 'typing' an hour later; ours expired 221 let s4: i64 = ty_sticky_active(1000, PR_MAGIC_4600) 222 let o4: i64 = ty_active(ctx, 40, 1, PR_MAGIC_4600) 223 var t4: i64=0 224 if s4==1 { if o4==0 { t4=1 } } 225 tcheck(t4, "T4 NEG-CONTROL sticky no-TTL model lies an hour later; ours expired" as *u8, fails) 226 227 // T5: scheduled send -- never early, delivered at due 228 let m5: i64 = sc_add(ctx, PR_MAGIC_2000, 0) 229 let e5: i64 = sc_tick(ctx, PR_MAGIC_1999) 230 let d5: i64 = sc_tick(ctx, PR_MAGIC_2000) 231 var t5: i64=0 232 if e5==0 { if d5==1 { if sc_sent[m5]==1 { t5=1 } } } 233 tcheck(t5, "T5 scheduled send: not delivered early, delivered at due tick" as *u8, fails) 234 235 // T6: silent send delivers with ZERO notification events; normal send emitted 1 236 let n_before: i64 = notif[0] 237 let m6: i64 = sc_add(ctx, PR_MAGIC_2100, 1) 238 sc_tick(ctx, PR_MAGIC_2100) 239 var t6: i64=0 240 if sc_sent[m6]==1 { if notif[0]==n_before { t6=1 } } 241 tcheck(t6, "T6 silent send: delivered with zero notification events" as *u8, fails) 242 243 // T7: IDEMPOTENT tick -- re-running the same tick cannot double-send (rule 10) 244 let dv_before: i64 = deliv[0] 245 let r7: i64 = sc_tick(ctx, PR_MAGIC_2100) 246 var t7: i64=0 247 if r7==0 { if deliv[0]==dv_before { t7=1 } } 248 tcheck(t7, "T7 delivery tick idempotent: re-run sends nothing twice" as *u8, fails) 249 250 sw(" fails=" as *u8); sn(fails[0]); sw("\n" as *u8) 251 if fails[0]==0 { sw("VERDICT: GREEN (presence/typing ephemeral by construction; scheduled + silent send idempotent)\n" as *u8); sys_exit(0) } 252 sw("VERDICT: RED\n" as *u8) 253 sys_exit(1) 254 return 1 255}