Capture guarded human gestures and verify agent administration
This commit is contained in:
1 parent
244f01630b
commit
adf0940e5f
32 files changed
+523
-52
No files matched your search
@@ -5,6 +5,17 @@ const require=createRequire(import.meta.url);
|
||||
const {buildInteractionEvidence,validateInteractionEvidence}=require('../apps/browser/evidence-capture.cjs');
|
||||
const {collectionAllowed,stripPendingEvidence,deliverAuditRecord,validatedEvidence}=require('../apps/browser/evidence-delivery.cjs');
|
||||
const sessionId='00000000-0000-4000-8000-000000000001';
|
||||
test('human-observer accepts observed click/submit only and uses its own audit source',async()=>{
|
||||
const policy={expiresAt:new Date(Date.now()+60000).toISOString(),evidence:{enabled:true,captureInteractions:true}},context={ready:true,deviceId:'device-a',policy};
|
||||
for(const action of ['click','submit']){
|
||||
const payload=buildInteractionEvidence({action,sessionId,url:'https://example.com/path?secret=1',sensitiveField:false,outcome:'observed',captureSource:'human-observer'},policy);
|
||||
assert.equal(payload.pageUrl,'https://example.com/');assert.equal(payload.outcome,'observed');
|
||||
for(const extra of [{outcome:'completed'},{action:'copy'},{bytes:1},{captureSource:'agent-adapter'}])assert.equal(validateInteractionEvidence({...payload,...extra}),false);
|
||||
const record={kind:'browser.interaction',eventId:sessionId,protectedEvidence:{deviceId:'device-a',type:'interaction',payload}},routes=[];
|
||||
assert.equal((await deliverAuditRecord({record,getContext:()=>context,send:async route=>{routes.push(route);return {id:sessionId,sourceEventId:1};}})).evidenceDelivered,true);
|
||||
assert.deepEqual(routes,['/api/device/events','/api/device/evidence']);record.kind='agent.action';await assert.rejects(deliverAuditRecord({record,getContext:()=>context,send:async()=>({})}),/source/);
|
||||
}
|
||||
});
|
||||
function fixture(){const context={ready:true,deviceId:'device-a',policy:{expiresAt:new Date(Date.now()+60000).toISOString(),evidence:{enabled:true,captureDownloads:true,captureInteractions:true}}};const payload=buildInteractionEvidence({action:'copy',sessionId,url:'https://example.com/private/password=secret?q=secret#secret',sensitiveField:false,outcome:'completed',captureSource:'guarded-clipboard',bytes:12},context.policy);const record={eventId:sessionId,kind:'clipboard.copy',protectedEvidence:{deviceId:'device-a',type:'interaction',payload}};return {context,payload,record};}
|
||||
test('automatic interaction capture requires observed completion and excludes path and sensitive data',()=>{const f=fixture();assert.equal(f.payload.pageUrl,'https://example.com/');assert.equal(validateInteractionEvidence(f.payload),true);for(const extra of [{content:'secret'},{contentSha256:'a'.repeat(64)},{target:{tag:'INPUT',label:'secret'}},{sensitiveField:true},{outcome:'authorized'},{captureSource:'page'},{bytes:16777217}])assert.equal(validateInteractionEvidence({...f.payload,...extra}),false);assert.equal(buildInteractionEvidence({action:'copy',sessionId,url:'https://example.com',sensitiveField:false,outcome:'authorized',captureSource:'guarded-clipboard'},f.context.policy),null);});
|
||||
test('type binding rejects cross-type payloads without attempting evidence send',async()=>{const f=fixture();assert.throws(()=>validatedEvidence(f.payload,'download'),/Invalid/);f.record.protectedEvidence.type='download';const calls=[];await assert.rejects(deliverAuditRecord({record:f.record,getContext:()=>f.context,send:async route=>{calls.push(route);return {};}}),/Invalid/);assert.deepEqual(calls,['/api/device/events']);});
|
||||
|
||||
Reference in new issue
Block a user