fix(multivalue): Wave-2 review fixes (MV-2/MV-4/MV-12)

- MV-2: guard unsupported element type before parse (no misleading re-wrap); add Float round-trip test
- MV-4: carry ElementDataType through the two validation-flatten ResolvedAttribute sites (ManagementActor.HandleValidateTemplate, BundleImporter.BuildFlattenedConfigForValidation) so MV-5 validation sees element type via every entry point
- MV-12: include ElementDataType in TemplateAttribute add/update audit payloads + fix stale docstring
This commit is contained in:
Joseph Doherty
2026-06-16 15:33:27 -04:00
parent 02aff2436e
commit 492b41f0fd
4 changed files with 16 additions and 2 deletions
@@ -72,6 +72,8 @@ public static class AttributeValueCodec
private static object? ParseScalar(string? s, DataType t) private static object? ParseScalar(string? s, DataType t)
{ {
if (s is null) throw new FormatException("List elements may not be null."); if (s is null) throw new FormatException("List elements may not be null.");
if (!IsValidElementType(t))
throw new FormatException($"Unsupported list element type '{t}'.");
var c = CultureInfo.InvariantCulture; var c = CultureInfo.InvariantCulture;
try try
{ {
@@ -524,6 +524,7 @@ public class ManagementActor : ReceiveActor
CanonicalName = a.Name, CanonicalName = a.Name,
Value = a.Value, Value = a.Value,
DataType = a.DataType.ToString(), DataType = a.DataType.ToString(),
ElementDataType = a.ElementDataType?.ToString(),
IsLocked = a.IsLocked, IsLocked = a.IsLocked,
DataSourceReference = a.DataSourceReference DataSourceReference = a.DataSourceReference
}).ToList(), }).ToList(),
@@ -1083,8 +1083,8 @@ public sealed class BundleImporter : IBundleImporter
/// enumerates for the "Template overwritten" action. /// enumerates for the "Template overwritten" action.
/// <para> /// <para>
/// Update detection compares every scalar field (Value, DataType, /// Update detection compares every scalar field (Value, DataType,
/// IsLocked, Description, DataSourceReference) — no field change → no /// ElementDataType, IsLocked, Description, DataSourceReference) — no field
/// audit row, so an idempotent overwrite produces no noise. /// change → no audit row, so an idempotent overwrite produces no noise.
/// </para> /// </para>
/// </summary> /// </summary>
private async Task SyncTemplateAttributesAsync( private async Task SyncTemplateAttributesAsync(
@@ -1146,6 +1146,7 @@ public sealed class BundleImporter : IBundleImporter
AttributeName = current.Name, AttributeName = current.Name,
current.Value, current.Value,
current.DataType, current.DataType,
current.ElementDataType,
current.IsLocked, current.IsLocked,
current.Description, current.Description,
current.DataSourceReference, current.DataSourceReference,
@@ -1176,6 +1177,7 @@ public sealed class BundleImporter : IBundleImporter
AttributeName = newAttr.Name, AttributeName = newAttr.Name,
newAttr.Value, newAttr.Value,
newAttr.DataType, newAttr.DataType,
newAttr.ElementDataType,
newAttr.IsLocked, newAttr.IsLocked,
newAttr.Description, newAttr.Description,
newAttr.DataSourceReference, newAttr.DataSourceReference,
@@ -2304,6 +2306,7 @@ public sealed class BundleImporter : IBundleImporter
CanonicalName = a.Name, CanonicalName = a.Name,
Value = a.Value, Value = a.Value,
DataType = a.DataType.ToString(), DataType = a.DataType.ToString(),
ElementDataType = a.ElementDataType?.ToString(),
IsLocked = a.IsLocked, IsLocked = a.IsLocked,
Description = a.Description, Description = a.Description,
DataSourceReference = a.DataSourceReference, DataSourceReference = a.DataSourceReference,
@@ -49,6 +49,14 @@ public class AttributeValueCodecTests
Assert.Equal("[\"ACME, Inc.\"]", Assert.Equal("[\"ACME, Inc.\"]",
AttributeValueCodec.Encode(new List<string> { "ACME, Inc." })); AttributeValueCodec.Encode(new List<string> { "ACME, Inc." }));
[Fact]
public void RoundTrip_FloatList()
{
var json = AttributeValueCodec.Encode(new List<float> { 1.5f, 2.25f, -3.75f });
var back = (IList<float>)AttributeValueCodec.Decode(json, DataType.List, DataType.Float)!;
Assert.Equal(new[] { 1.5f, 2.25f, -3.75f }, back);
}
[Fact] [Fact]
public void Encode_DoubleList_IsInvariant() public void Encode_DoubleList_IsInvariant()
{ {