fix(coding): remediate ML-07 plugin authority
This commit is contained in:
@@ -31,13 +31,25 @@ export type PluginBilling = {
|
||||
export type CodingPluginItem = {
|
||||
id: string;
|
||||
version: string;
|
||||
contractVersion: number;
|
||||
requiresBackend: boolean;
|
||||
displayName: string;
|
||||
description: string;
|
||||
enabled: boolean;
|
||||
state: CodingPluginEffectiveState;
|
||||
backend: PluginBackend;
|
||||
skills: Array<{ id: string; assignedAgentIds: string[] }>;
|
||||
capabilities: Array<{ id: string; operations: Array<{ id: string; billing: PluginBilling }> }>;
|
||||
capabilities: Array<{ id: string; operations: Array<{
|
||||
id: string;
|
||||
billing: PluginBilling;
|
||||
tool: {
|
||||
name: string;
|
||||
label: string;
|
||||
description: string;
|
||||
mutation: 'read' | 'write' | 'destructive';
|
||||
permissions: string[];
|
||||
} | null;
|
||||
}> }>;
|
||||
settingsSurface: string | null;
|
||||
};
|
||||
|
||||
@@ -120,13 +132,18 @@ function billing(value: unknown): PluginBilling {
|
||||
|
||||
function pluginItem(value: unknown): CodingPluginItem {
|
||||
const source = record(value, 'plugin');
|
||||
exact(source, ['id', 'version', 'displayName', 'description', 'enabled', 'state', 'backend', 'skills', 'capabilities', 'settingsSurface'], 'plugin');
|
||||
if (typeof source.enabled !== 'boolean') throw new Error('plugin.enabled is invalid');
|
||||
exact(source, ['id', 'version', 'contractVersion', 'requiresBackend', 'displayName', 'description', 'enabled', 'state', 'backend', 'skills', 'capabilities', 'settingsSurface'], 'plugin');
|
||||
if (typeof source.enabled !== 'boolean' || typeof source.requiresBackend !== 'boolean'
|
||||
|| !Number.isSafeInteger(source.contractVersion) || (source.contractVersion as number) < 1) {
|
||||
throw new Error('plugin metadata is invalid');
|
||||
}
|
||||
const state = string(source.state, 'plugin.state', 32) as CodingPluginEffectiveState;
|
||||
if (!['unavailable', 'disabled', 'identity_required', 'authentication_required', 'configuration_required', 'ready', 'degraded'].includes(state)) throw new Error('plugin.state is invalid');
|
||||
if (!Array.isArray(source.skills) || !Array.isArray(source.capabilities)) throw new Error('plugin arrays are invalid');
|
||||
return {
|
||||
id: string(source.id, 'plugin.id', 128), version: string(source.version, 'plugin.version', 64),
|
||||
contractVersion: source.contractVersion as number,
|
||||
requiresBackend: source.requiresBackend,
|
||||
displayName: string(source.displayName, 'plugin.displayName'), description: string(source.description, 'plugin.description', 512),
|
||||
enabled: source.enabled, state, backend: backend(source.backend),
|
||||
skills: source.skills.map((value) => {
|
||||
@@ -138,8 +155,24 @@ function pluginItem(value: unknown): CodingPluginItem {
|
||||
const capability = record(value, 'capability'); exact(capability, ['id', 'operations'], 'capability');
|
||||
if (!Array.isArray(capability.operations)) throw new Error('capability.operations is invalid');
|
||||
return { id: string(capability.id, 'capability.id', 128), operations: capability.operations.map((value) => {
|
||||
const operation = record(value, 'operation'); exact(operation, ['id', 'billing'], 'operation');
|
||||
return { id: string(operation.id, 'operation.id', 128), billing: billing(operation.billing) };
|
||||
const operation = record(value, 'operation'); exact(operation, ['id', 'billing', 'tool'], 'operation');
|
||||
let tool: CodingPluginItem['capabilities'][number]['operations'][number]['tool'] = null;
|
||||
if (operation.tool !== null) {
|
||||
const sourceTool = record(operation.tool, 'operation.tool');
|
||||
exact(sourceTool, ['name', 'label', 'description', 'mutation', 'permissions'], 'operation.tool');
|
||||
const mutation = string(sourceTool.mutation, 'operation.tool.mutation', 16);
|
||||
if (!['read', 'write', 'destructive'].includes(mutation) || !Array.isArray(sourceTool.permissions)) {
|
||||
throw new Error('operation.tool is invalid');
|
||||
}
|
||||
tool = {
|
||||
name: string(sourceTool.name, 'operation.tool.name', 64),
|
||||
label: string(sourceTool.label, 'operation.tool.label', 128),
|
||||
description: string(sourceTool.description, 'operation.tool.description', 512),
|
||||
mutation: mutation as 'read' | 'write' | 'destructive',
|
||||
permissions: sourceTool.permissions.map((permission) => string(permission, 'operation.tool.permission', 64)),
|
||||
};
|
||||
}
|
||||
return { id: string(operation.id, 'operation.id', 128), billing: billing(operation.billing), tool };
|
||||
}) };
|
||||
}),
|
||||
settingsSurface: source.settingsSurface === null ? null : string(source.settingsSurface, 'plugin.settingsSurface', 64),
|
||||
|
||||
Reference in New Issue
Block a user