social-kit / dist / selftest.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import { $APP, shadow$provide } from "./shared.js";
import "./index.js";
var Y=function(a,b){if(!$APP.n(a))throw Error("social-kit self-test FAILED: "+$APP.p(b));},Hd=function(){if(typeof globalThis.localStorage==="undefined"){var a=new Map;globalThis.localStorage=function(){return{getItem:function(b){b=a.get(b);return b===void 0?null:b},setItem:function(b,c){a.set(b,c)},removeItem:function(b){a.delete(b)}}}()}},Id=function(a){var b=$APP.Ca.newSeed();return $APP.Ca.fromSeed(b).then(function(c){return $APP.Ia(b).then(function(d){return $APP.Ja(c,d.pubB64).then(function(e){return{identity:c,
x:d,xCert:e,name:a,seed:b}})})})},Z=function(a){return a.identity.publicKeyB64},Jd=function(a,b){return $APP.G(a,$APP.I(Z(b)),Z(b),b.x.pubB64,"freq",{msg:"salut"},void 0).then(function(c){return $APP.H(b.x,$APP.I(Z(b)),c.bytes).then(function(d){Y(d!=null&&d.t==="freq"&&d.from.pub===Z(a),"envelope roundtrip");Y(d.from.name==="ana"&&d.body.msg==="salut","envelope content");return $APP.H(b.x,$APP.I(Z(a)),c.bytes).then(function(e){Y(e==null,"envelope ctx-bound");return $APP.H(a.x,$APP.I(Z(b)),c.bytes).then(function(f){Y(f==
null,"envelope sealed to recipient");f=(new TextDecoder).decode(c.bytes);var g=f.length>>1;f=""+$APP.p(f.slice(0,g))+$APP.p(f.charAt(g)==="A"?"B":"A")+$APP.p(f.slice(g+1));f=(new TextEncoder).encode(f);return $APP.H(b.x,$APP.I(Z(b)),f).then(function(k){Y(k==null,"tamper drop");return d})})})})})},Kd=function(a,b){return $APP.Db(a.x,Z(a),Z(b),b.x.pubB64).then(function(c){return $APP.Db(b.x,Z(b),Z(a),a.x.pubB64).then(function(d){Y(c.topic===d.topic&&c.mailboxRoomId===d.mailboxRoomId,"pair channel symmetric");
return function(){var e=Z(a),f={k:"b",name:"ana"},g=c.seal;return g.i?g.i(e,f):g.call(null,e,f)}().then(function(e){return function(){var f=[Z(a)],g=d.open;return g.i?g.i(e,f):g.call(null,e,f)}().then(function(f){Y(f!=null&&f.payload.name==="ana","pair seal/open");return Id("eve").then(function(g){return $APP.Db(g.x,Z(g),Z(b),b.x.pubB64).then(function(k){Y(k.topic!==c.topic,"outsider derives a different channel");return function(){var h=[Z(g)],l=d.open;return l.i?l.i(e,h):l.call(null,e,h)}().then(function(h){Y(h==
null,"wrong member list rejected");return $APP.Eb(a.seed).then(function(l){return $APP.Eb(a.seed).then(function(m){Y(l.topic===m.topic&&l.topic!==c.topic,"self channel deterministic + distinct");return $APP.Fb(Z(a)).then(function(q){return $APP.Fb(Z(a)).then(function(t){Y(q===t,"inbox id stable");return g})})})})})})})})})})})},Ld=function(a,b,c,d){var e=new $APP.ed("t1");Y($APP.eb(e,d,void 0,void 0),"freq applies");Y(function(){var g=e.get(Z(a));return g!=null&&g.state==="in"}(),"request pending");
e.markFriend(Z(a));var f=new $APP.ed("t2");Y(1===f.merge(e.socBlob()),"merge adds");Y(function(){var g=f.get(Z(a));return g!=null&&g.state==="friend"}(),"merge keeps state");f.block(Z(a));Y(0===f.merge(e.socBlob()),"tombstone beats re-add");Y(0===f.merge({v:1,friends:[{pub:"__proto__",x:"x",xs:"y",state:"friend"}],blocked:[],ts:0}),"malformed records dropped");d={v:1,friends:[{xs:c.xCert,addedTs:Date.now(),petTs:0,x:c.x.pubB64,name:"bestie",lastApp:"",pub:Z(c),pet:"",state:"friend",lastSeenTs:0}],
blocked:[],ts:Date.now()};return $APP.G(c,$APP.I(Z(b)),Z(b),b.x.pubB64,"fsync",{soc:d},void 0).then(function(g){return $APP.H(b.x,$APP.I(Z(b)),g.bytes).then(function(k){Y(k!=null,"forged fsync opens (the envelope itself is valid)");var h=new $APP.ed("t3");Y(!1===$APP.eb(h,k,{},Z(b)),"forged fsync dropped by self-origin guard");Y(h.list().length===0,"forged fsync folded nothing");return $APP.G(b,$APP.I(Z(b)),Z(b),b.x.pubB64,"fsync",{soc:e.socBlob()},void 0).then(function(l){return $APP.H(b.x,$APP.I(Z(b)),
l.bytes).then(function(m){Y(!0===$APP.eb(h,m,{},Z(b)),"own fsync still folds");return null})})})})},Md=function(){function a(g,k,h,l,m){return{name:g,hue:k,glyph:h,lang:l,ts:m}}var b=a("ana",12,"\ud83e\udd8a","ro",1E3),c=a("",null,null,null,9E3);Y($APP.F($APP.J(b,c))===$APP.E(b),"blank import never clobbers a real profile");c=a("ana!",null,null,null,2E3);Y($APP.F($APP.J(b,c))===$APP.E(c),"newer non-blank wins wholesale");c=a("bea",200,"\ud83d\udc1d","hu",1);var d=a("",null,"\ud83e\udd8a",null,1E3),
e=$APP.J(d,c);Y(e.name==="bea"&&e.hue===200&&e.glyph==="\ud83e\udd8a"&&e.lang==="hu"&&e.ts===1E3,"older only backfills blanks");Y($APP.F($APP.J(d,$APP.J(d,c)))===$APP.E(e),"backfill fold idempotent");d=a("ana",12,null,null,500);var f=a("zoe",null,null,null,500);e=$APP.J(d,f);Y($APP.E(e)===$APP.F($APP.J(f,d)),"equal-ts fold converges both ways");f=($APP.oa($APP.E(d),$APP.E(f))>0?d:f).name;Y(e.name===f&&e.hue===12&&e.ts===500,"equal-ts tiebreak deterministic");Y($APP.F($APP.J(d,e))===$APP.E(e),"equal-ts fold idempotent");
Y($APP.F($APP.J(c,$APP.J(c,b)))===$APP.F($APP.J(c,b)),"wholesale fold idempotent");Y($APP.Hb(null)==null&&$APP.Hb({name:"x"})==null,"profile sync shape-checked");b=$APP.Hb({name:"x".repeat(99),hue:720,glyph:"ab",lang:"no way",ts:Date.now()+863136E5});Y(32===Array.from(b.name).length&&b.hue===null&&b.glyph==="a"&&b.lang===null&&b.ts<=Date.now()+12E4,"profile sync clamped")},Nd=function(){function a(e,f){return{state:e,ts:f}}var b={board:a({n:2},3E3),chat:a({n:1},1E3)},c={chat:a({n:9},2E3),game1:a({n:3},
500)},d=$APP.M(b,c);Y(d.chat.ts===2E3,"newer entry wins its key wholesale");Y(d.board.ts===3E3,"a key only the local side has survives");Y(d.game1.ts===500,"a key only the remote side has is adopted, however old");Y($APP.E(d)===$APP.F($APP.M(c,b)),"apps fold commutes");Y($APP.F($APP.M(b,d))===$APP.E(d),"apps fold idempotent");b=$APP.M(b,{board:a({n:7},9E3),chat:a({n:0},1)});Y(b.board.ts===9E3&&b.chat.ts===1E3,"each key folds on its own timestamp");b={chat:a({n:1},777)};c={chat:a({n:2},777)};d=$APP.M(b,
c);Y($APP.E(d)===$APP.F($APP.M(c,b)),"equal-ts apps fold converges from both roles");Y($APP.F($APP.M(d,b))===$APP.E(d),"equal-ts apps fold idempotent");Y($APP.K(null)==null&&$APP.K([])==null&&$APP.K({})==null&&$APP.K({chat:{state:1}})==null,"apps sync shape-checked");b=JSON.parse('{"__proto__":{"state":"p","ts":9},"constructor":{"state":"c","ts":9}}');c=$APP.M(b,{});Y($APP.F(Object.keys(c))==='["constructor"]',"the fold drops __proto__ and keeps constructor as data");Y(Object.getPrototypeOf(c)===
Object.prototype&&c.state===void 0,"the fold's output is not poisonable through __proto__");Y($APP.F(Object.keys($APP.K(b)))==='["constructor"]',"sanitize drops __proto__ too");b=$APP.K({zed:a(1,5),chat:a({ok:!0},Date.now()+863136E5),"BAD KEY":a(1,5),big:a("x".repeat(2E4),5),nan:a(1,NaN)});Y($APP.F(Object.keys(b))==='["chat","zed"]',"apps sync drops bad keys and entries, and emits in a fixed order");Y(b.chat.ts<=Date.now(),"apps sync ts clamped to now, never ahead of it");Y(b.zed.ts===5,"an honest past ts is left exactly alone")},
Od=function(a,b){var c=$APP.ab("https://ardegazu.ro/",{pub:Z(a),x:a.x.pubB64,xs:a.xCert,name:"ana"});return $APP.cb((new URL(c)).hash).then(function(d){Y(d!=null&&d.pub===Z(a)&&d.name==="ana","friend link roundtrip");d=c.replace(a.x.pubB64,b.x.pubB64);return $APP.cb((new URL(d)).hash).then(function(e){Y(e==null,"forged link cert rejected");return null})})},Pd=function(a,b,c){var d={v:1,g:"game1.ardegazu.ro/v2",m:"classic",r:"roomhashroomhashroomha",ts:Date.now(),n:2,sc:[{p:Z(a),nm:"ana",s:420},{p:Z(b),
nm:"bogdan",s:300}]};return $APP.Qc(a.identity,d).then(function(e){return $APP.Qc(b.identity,d).then(function(f){var g=Object.assign({},d);g.sig=[e,f];return $APP.U(g,void 0).then(function(k){Y(k!=null,"co-signed receipt verifies");k=Object.assign({},g);k.sig=[e];return $APP.U(k,void 0).then(function(h){Y(h==null,"1-sig receipt rejected");h=Object.assign({},g);var l=Object.assign({},g.sc[0]);l.s=999999;h.sc=[l,g.sc[1]];return $APP.U(h,void 0).then(function(m){Y(m==null,"tampered score rejected");
return $APP.Qc(c.identity,d).then(function(q){var t=Object.assign({},g);t.sig=[e,q];return $APP.U(t,void 0).then(function(z){Y(z==null,"non-player signer rejected");return $APP.Pc(g).then(function(v){return $APP.Pc(d).then(function(y){Y(v===y,"hash ignores sigs");Y(/^\d{4}-W\d{2}$/.test($APP.Rc(Date.now())),"iso week shape");y=$APP.Xc([g]);Y(y[0].pub===Z(a)&&y[0].best===420,"aggregate top row");return null})})})})})})})})})};export const runSocialKitSelfTest=function(){return Promise.resolve(null).then(function(){Hd();Y($APP.E({b:1,a:[2,{z:null,y:"s"}],c:void 0})==='{"a":[2,{"y":"s","z":null}],"b":1}',"canon shape");return Id("ana").then(function(a){return Id("bogdan").then(function(b){return Jd(a,b).then(function(c){return Kd(a,b).then(function(d){return Ld(a,b,d,c).then(function(){Md();Nd();return Od(a,b).then(function(){return Pd(a,b,d).then(function(){console.info("✅ social-kit self-test passed")})})})})})})})})};

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/social-kit.git