Files

31 lines
2.0 KiB
JavaScript

// Non-executing organization view. Disabled/missing capabilities carry only a validated name.
import { buildRegistry } from '../../organization/src/composition.mjs';
import { declaredSet, bad } from './manifest.mjs';
import { verifiedPlugin } from './pinned.mjs';
import { hasModule } from './loader.mjs';
export {pluginName} from "../../organization/src/vocabulary.mjs";
import {pluginName} from "../../organization/src/vocabulary.mjs";
export function organizationPlugins(dataRoot,settings = {}) {
const names=new Set(Object.entries(settings).flatMap(([kind,v])=>(Array.isArray(v)?v:[v]).filter(name=>!hasModule(kind,name))));
const manifests=[],refused=[];
if(dataRoot!==null) for(const name of names){try {const m=verifiedPlugin(dataRoot,name).manifest;
if(m.kinds.every(k=>(Array.isArray(settings[k])?settings[k]:[settings[k]]).includes(name)))manifests.push(m);
}catch {refused.push(name);}}
const registry=buildRegistry({plugins:manifests.map(declaredSet)});
return {registry,manifests,refused,roleTemplates:manifests.flatMap(m=>m.roleTemplates)};
}
export function assertPluginCapabilities(role,view) {
const check = (cap,registered) => {
const name=pluginName(cap);if(!name)return;
if(!view.manifests.some(m=>m.name===name))bad('plugin-disabled',name);
if(!registered)bad('invalid-request');
};
for(const tool of role.tools ?? [])check(tool,view.registry.tools.includes(tool));
for(const action of [...(role.authority?.withinRole ?? []),...(role.authority?.crossRole ?? [])])check(action,view.registry.actions.includes(action));
const credentials=Array.isArray(role.credentials) ? role.credentials : Object.keys(role.credentials ?? {}).map(service=>({service}));
for(const credential of credentials) {
const {service,scopes}=credential;check(service,Object.hasOwn(view.registry.services,service));
if(pluginName(service) && scopes!==undefined && (!Array.isArray(scopes) || scopes.some(s=>!view.registry.services[service].scopes.includes(s))))bad('invalid-request');
}
}