Implement managed browser security, individual agents and observability

This commit is contained in:
Karl committed 2026-10-13 16:58:15 +02:00
1 parent ff482ebe23
commit ea448de2d4
172 files changed
+5404 -347

No files matched your search

+19
View File
@@ -0,0 +1,19 @@
import test from 'node:test';import assert from 'node:assert/strict';import {mkdtempSync,rmSync,readdirSync,readFileSync} from 'node:fs';import {tmpdir} from 'node:os';import {join,resolve} from 'node:path';import {spawn} from 'node:child_process';import {createServer} from 'node:net';
test('actual Windows protected collector rotates encrypted exports and rejects oversized storage without acknowledgement',{skip:process.platform!=='win32'},async t=>{
const root=mkdtempSync(join(tmpdir(),'safetynet-collector-http-'));const probe=createServer();await new Promise(r=>probe.listen(0,'127.0.0.1',r));const port=probe.address().port;await new Promise(r=>probe.close(r));
const child=spawn(process.execPath,[resolve('scripts/debug-collector.mjs')],{windowsHide:true,stdio:'pipe',env:{...process.env,DEBUG_COLLECTOR_DIRECTORY:root,DEBUG_COLLECTOR_PORT:String(port),DEBUG_COLLECTOR_SEGMENT_BYTES:'1024',DEBUG_COLLECTOR_RETIRED_SEGMENTS:'1'}});
let output='';child.stdout.on('data',b=>output+=b);child.stderr.on('data',b=>output+=b);t.after(async()=>{if(child.exitCode===null){child.kill();await new Promise(r=>child.once('exit',r));}assert.ok(root.startsWith(join(tmpdir(),'safetynet-collector-http-')));rmSync(root,{recursive:true,force:true});});
const base=`http://127.0.0.1:${port}`;let health;
for(let i=0;i<80;i++){if(child.exitCode!==null)throw Error('Collector test process failed: '+output);try{health=await (await fetch(base+'/health')).json();break;}catch{await new Promise(r=>setTimeout(r,100));}}
assert.ok(health);const marker='SYNTHETIC_COLLECTOR_ROTATION';const post=body=>fetch(base+'/v1/logs',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(body)});
for(let i=0;i<12;i++)assert.equal((await post({resourceLogs:[{scopeLogs:[{logRecords:[{body:{stringValue:marker}}]}]}]})).status,200);
health=await (await fetch(base+'/api/summary')).json();assert.equal(health.requests,12);assert.equal(health.counts.logs,12);assert.ok(health.rotations>1);assert.ok(health.droppedSegments>0);assert.equal(health.retiredSegments,1);assert.ok(health.activeBytes+health.retiredBytes<=2048);
for(const name of readdirSync(root).filter(n=>n.endsWith('.ndjson'))){const content=readFileSync(join(root,name),'utf8');assert.equal(content.includes(marker),false);for(const line of content.trim().split('\n')){const envelope=JSON.parse(line);assert.equal(envelope.v,1);assert.ok(envelope.nonce&&envelope.tag&&envelope.ciphertext);}}
assert.equal((await post({large:'x'.repeat(2048)})).status,507);health=await (await fetch(base+'/health')).json();assert.equal(health.requests,12);assert.equal(health.rejectedWrites,1);
const before=structuredClone(health);const tracePost=body=>fetch(base+'/v1/traces',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(body)});
const span={traceId:'1234567890abcdef1234567890abcdef',spanId:'1234567890abcdef',name:'synthetic.stage',startTimeUnixNano:'10',endTimeUnixNano:'11'};
for(const bad of [{...span,endTimeUnixNano:'9'},{...span,startTimeUnixNano:'18446744073709551616'},{...span,traceId:123},{...span,endTimeUnixNano:'oops'},{...span,attributes:{}}])assert.equal((await tracePost({resourceSpans:[{scopeSpans:[{spans:[bad]}]}]})).status,400);
assert.equal((await tracePost({resourceSpans:{}})).status,400);assert.equal((await post({resourceLogs:[{scopeLogs:{}}]})).status,400);
health=await (await fetch(base+'/health')).json();for(const field of ['requests','storedBytes','activeBytes','legacyBytes','retiredBytes','rotations','droppedSegments','droppedBytes','rejectedWrites','retainedSpans'])assert.equal(health[field],before[field]);assert.deepEqual(health.counts,before.counts);
assert.equal((await tracePost({resourceSpans:[]})).status,200);assert.equal((await tracePost({resourceSpans:[{scopeSpans:[{spans:[span]}]}]})).status,200);const trace=await (await fetch(base+'/api/trace/'+span.traceId)).json();assert.equal(trace.spans[0].durationMs,0.000001);
});