fix(coding): remediate ML-07 plugin authority

This commit is contained in:
2026-08-27 20:40:58 +08:00
parent 9407c67df2
commit cf13aa7eba
29 changed files with 1008 additions and 214 deletions

View File

@@ -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),