merge: wave 2 executor (01-02) into main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
a5b8fcf9d3
commit
aa1a78d7d9
1081 files changed
+445341
No files matched your search
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @fileoverview Validates plugin instance configuration against its JSON Schema.
|
||||
*
|
||||
* Uses Ajv to validate `configJson` values against the `instanceConfigSchema`
|
||||
* declared in a plugin's manifest. This ensures that invalid configuration is
|
||||
* rejected at the API boundary, not discovered later at worker startup.
|
||||
*
|
||||
* @module server/services/plugin-config-validator
|
||||
*/
|
||||
|
||||
import Ajv, { type ErrorObject } from "ajv";
|
||||
import addFormats from "ajv-formats";
|
||||
import type { JsonSchema } from "@paperclipai/shared";
|
||||
|
||||
export interface ConfigValidationResult {
|
||||
valid: boolean;
|
||||
errors?: { field: string; message: string }[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a config object against a JSON Schema.
|
||||
*
|
||||
* @param configJson - The configuration values to validate.
|
||||
* @param schema - The JSON Schema from the plugin manifest's `instanceConfigSchema`.
|
||||
* @returns Validation result with structured field errors on failure.
|
||||
*/
|
||||
export function validateInstanceConfig(
|
||||
configJson: Record<string, unknown>,
|
||||
schema: JsonSchema,
|
||||
): ConfigValidationResult {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const AjvCtor = (Ajv as any).default ?? Ajv;
|
||||
const ajv = new AjvCtor({ allErrors: true });
|
||||
// ajv-formats v3 default export is a FormatsPlugin object; call it as a plugin.
|
||||
const applyFormats = (addFormats as any).default ?? addFormats;
|
||||
applyFormats(ajv);
|
||||
// Register the secret-ref format used by plugin manifests to mark fields that
|
||||
// hold a Paperclip secret UUID rather than a raw value. The format is a UI
|
||||
// hint only — UUID validation happens in the secrets handler at resolve time.
|
||||
ajv.addFormat("secret-ref", { validate: () => true });
|
||||
const validate = ajv.compile(schema);
|
||||
const valid = validate(configJson);
|
||||
|
||||
if (valid) {
|
||||
return { valid: true };
|
||||
}
|
||||
|
||||
const errors = (validate.errors ?? []).map((err: ErrorObject) => ({
|
||||
field: err.instancePath || "/",
|
||||
message: err.message ?? "validation failed",
|
||||
}));
|
||||
|
||||
return { valid: false, errors };
|
||||
}
|
||||
Reference in new issue
Block a user