Implement managed browser security, individual agents and observability
This commit is contained in:
1 parent
ff482ebe23
commit
ea448de2d4
172 files changed
+5404
-347
No files matched your search
@@ -0,0 +1,45 @@
|
||||
'use strict';
|
||||
// Fixed native operations only. A model never supplies URLs, scripts or handles.
|
||||
function createLibraryOrganization({capture,assertCurrent,propose,commit,applyTabs,inspect,audit,changed=()=>{},autoAllowed=()=>false}={}){
|
||||
if([capture,assertCurrent,propose,commit,applyTabs,inspect,audit].some(fn=>typeof fn!=='function'))throw TypeError('Invalid library callbacks');
|
||||
let busy=false;const proposals=new Map();
|
||||
const checkInput=input=>{if(!input||typeof input!=='object'||Array.isArray(input)||Object.keys(input).some(k=>!['proposalId','confirm','autoApply'].includes(k))||typeof input.proposalId!=='string'||input.proposalId.length>128)throw Error('Invalid organization request');};
|
||||
async function plan({signal}={}){
|
||||
if(busy)throw Error('Library organization is already running');busy=true;changed();
|
||||
try{
|
||||
const current=snapshot=>{if(signal?.aborted)throw Error('Organization action cancelled');assertCurrent(snapshot);};
|
||||
const snapshot=await capture();current(snapshot);await inspect(snapshot);current(snapshot);
|
||||
const result=await propose(snapshot);current(snapshot);
|
||||
if(typeof result?.proposalId!=='string'||result.proposalId.length>128)throw Error('Invalid library proposal');
|
||||
if(snapshot.snapshotHash&&(result.binding?.snapshotHash!==snapshot.snapshotHash||result.binding?.policyVersion!==snapshot.policyVersion||result.binding?.bookmarkRevision!==snapshot.bookmarkRevision))throw Error('Invalid organization proposal binding');
|
||||
const core=await import('../../packages/core/library.mjs');
|
||||
const validated=core.validateLibraryPlan(result.plan,{bookmarks:snapshot.bookmarks,tabs:snapshot.tabs});
|
||||
// Keep authoritative plan and binding in native memory, never renderer input.
|
||||
proposals.clear();proposals.set(result.proposalId,{snapshot,plan:validated,expires:Date.now()+300000});
|
||||
await audit('library.ai.proposed',`bookmarks-${validated.bookmarks.length}:tabs-${validated.tabs.length}`);
|
||||
return {...result,plan:structuredClone(validated)};
|
||||
}finally{busy=false;changed();}
|
||||
}
|
||||
async function apply(input,{signal}={}){
|
||||
checkInput(input);if(busy)throw Error('Library organization is already running');
|
||||
const stored=proposals.get(input.proposalId);
|
||||
if(!stored||stored.expires<=Date.now())throw Error('Organization proposal expired. Generate a fresh proposal.');
|
||||
if(input.confirm!==true&&!(input.autoApply===true&&autoAllowed()))throw Error('Review and confirm the organization proposal');
|
||||
if(signal?.aborted)throw Error('Organization action cancelled');assertCurrent(stored.snapshot);busy=true;changed();
|
||||
let committed=false;
|
||||
try{
|
||||
const result=await commit(input.proposalId,stored.snapshot,input.autoApply===true);committed=true;
|
||||
// Bookmarks are committed centrally. Navigation or policy changes can occur
|
||||
// meanwhile: never silently apply stale tab assignments after such a change.
|
||||
if(signal?.aborted)throw Error('Organization action cancelled');assertCurrent(stored.snapshot,{afterCommit:true,result});
|
||||
applyTabs(stored.plan.tabs,result);proposals.delete(input.proposalId);
|
||||
await audit('library.ai.applied',`bookmarks-${stored.plan.bookmarks.length}:tabs-${stored.plan.tabs.length}`);
|
||||
return {completed:true,bookmarkRevision:result.revision,tabCount:stored.plan.tabs.length};
|
||||
}catch(error){
|
||||
if(committed){proposals.delete(input.proposalId);await audit('library.ai.reconcile','central-bookmarks-committed');throw Error('Bookmarks were organized centrally; tabs were unchanged because the browser context changed. Refresh the library.');}
|
||||
throw error;
|
||||
}finally{busy=false;changed();}
|
||||
}
|
||||
return {plan,apply,isBusy:()=>busy};
|
||||
}
|
||||
module.exports={createLibraryOrganization};
|
||||
Reference in new issue
Block a user