fix(m9/T32b): resolve $ref in InboundAPI runtime validators (no deploy-passes/runtime-400); diamond test; ref-annotation message

This commit is contained in:
Joseph Doherty
2026-06-18 12:16:39 -04:00
parent 26e2cdef23
commit 71d5722692
9 changed files with 424 additions and 25 deletions
@@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.Scripting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ZB.MOM.WW.ScadaBridge.Commons.Entities.InboundApi;
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services;
using ZB.MOM.WW.ScadaBridge.Commons.Messages.InboundApi;
using ZB.MOM.WW.ScadaBridge.Commons.Types;
@@ -307,11 +308,24 @@ public class InboundScriptExecutor
? JsonSerializer.Serialize(result)
: null;
// M9-T32b: thread the JSON-Schema $ref resolution seam into return
// validation so a method whose ReturnDefinition uses a {"$ref":"lib:Name"}
// resolves the reference at RUNTIME (not just at deploy time). The
// shared-schema library is pre-loaded ONCE from the per-execution DI scope
// (the seam the validator consumes is synchronous), and ONLY when the
// definition actually uses a $ref — a $ref-free return definition skips the
// repository round-trip entirely. A dangling ref surfaces as a descriptive
// validation failure naming the missing reference, not an opaque parse error.
var sharedSchemaRepo =
(scope?.ServiceProvider ?? _serviceProvider).GetService<ISharedSchemaRepository>();
var resolveRef = await SchemaRefResolver.BuildAsync(
sharedSchemaRepo, [method.ReturnDefinition], cts.Token);
// InboundAPI-014: validate the script's return value against the
// method's declared ReturnDefinition. A method whose script returns a
// shape inconsistent with its definition must not silently emit a
// malformed 200 — surface it as a script failure (500) and log.
var returnValidation = ReturnValueValidator.Validate(resultJson, method.ReturnDefinition);
var returnValidation = ReturnValueValidator.Validate(resultJson, method.ReturnDefinition, resolveRef);
if (!returnValidation.IsValid)
{
_logger.LogWarning(