fix(m9/T32b): resolve $ref in InboundAPI runtime validators (no deploy-passes/runtime-400); diamond test; ref-annotation message
This commit is contained in:
@@ -36,8 +36,21 @@ public static class ReturnValueValidator
|
||||
/// </summary>
|
||||
/// <param name="resultJson">The JSON-serialized script return value to validate.</param>
|
||||
/// <param name="returnDefinition">JSON Schema describing the method's return value, or null/empty to skip validation. The legacy flat-array form is also accepted.</param>
|
||||
/// <param name="resolveRef">
|
||||
/// M9-T32b: optional JSON-Schema <c>$ref</c> resolution seam mapping a
|
||||
/// <c>{"$ref":"lib:Name"}</c> reference target's name to the referenced schema JSON
|
||||
/// (or <c>null</c> when the library entry does not exist). The executor pre-loads the
|
||||
/// shared-schema library (backed by <c>ISharedSchemaRepository</c>) and supplies it
|
||||
/// ONLY when the definition actually uses a <c>$ref</c>. <c>null</c> means no resolver:
|
||||
/// schemas with no <c>$ref</c> behave exactly as before; a <c>$ref</c> with no resolver
|
||||
/// (or a dangling one) is surfaced as a CLEAR invalid result naming the missing
|
||||
/// reference — NOT an opaque parse-error from a thrown <see cref="JsonException"/>.
|
||||
/// </param>
|
||||
/// <returns>A <see cref="ReturnValidationResult"/> indicating success or describing the validation failures.</returns>
|
||||
public static ReturnValidationResult Validate(string? resultJson, string? returnDefinition)
|
||||
public static ReturnValidationResult Validate(
|
||||
string? resultJson,
|
||||
string? returnDefinition,
|
||||
Func<string, string?>? resolveRef = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(returnDefinition))
|
||||
{
|
||||
@@ -45,10 +58,14 @@ public static class ReturnValueValidator
|
||||
return ReturnValidationResult.Valid();
|
||||
}
|
||||
|
||||
InboundApiSchema? schema;
|
||||
// M9-T32b: parse through the ref-COLLECTING path so a {"$ref":"lib:Name"} the
|
||||
// resolver can satisfy is resolved inline, and a dangling/cyclic/over-depth ref is
|
||||
// surfaced as a descriptive "could not be resolved" message rather than an opaque
|
||||
// "Invalid return definition" from a swallowed JsonException.
|
||||
SchemaParseResult parsed;
|
||||
try
|
||||
{
|
||||
schema = InboundApiSchema.Parse(returnDefinition);
|
||||
parsed = InboundApiSchema.ParseWithRefs(returnDefinition, resolveRef);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
@@ -56,6 +73,14 @@ public static class ReturnValueValidator
|
||||
"Invalid return definition in method configuration");
|
||||
}
|
||||
|
||||
if (parsed.UnresolvedReferences.Count > 0)
|
||||
{
|
||||
return ReturnValidationResult.Invalid(
|
||||
$"Return definition references {ParameterValidator.DescribeUnresolved(parsed.UnresolvedReferences)} which could not be resolved");
|
||||
}
|
||||
|
||||
InboundApiSchema? schema = parsed.Schema;
|
||||
|
||||
// A schema that declares no constraints (e.g. an object schema with no
|
||||
// fields) leaves the return value unconstrained.
|
||||
if (schema is null || (schema.Type == "object" && schema.Fields.Count == 0))
|
||||
|
||||
Reference in New Issue
Block a user