feat: add strict legacy probe override schema

This commit is contained in:
codex
2026-08-05 16:33:13 +03:00
parent 9c49ebf1e2
commit 8764348a75
2 changed files with 48 additions and 0 deletions
@@ -0,0 +1,39 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Launcher.Next.Application;
public sealed record LegacyProbeOverride(
int SchemaVersion,
string Mode,
string SettingsXml,
string DownloadListXml,
string CompatibilityOverlay,
string SelectedPattern,
string EvidenceOutputRoot);
public static class LegacyProbeOverrideParser
{
private static readonly JsonSerializerOptions Options = new()
{
PropertyNameCaseInsensitive = true,
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow
};
public static LegacyProbeOverride Parse(string json)
{
try
{
var value = JsonSerializer.Deserialize<LegacyProbeOverride>(json, Options)
?? throw new InvalidOperationException("LEGACY_PROBE_OVERRIDE_MISSING");
if (value.SchemaVersion != 1) throw new InvalidOperationException("LEGACY_PROBE_OVERRIDE_SCHEMA_UNSUPPORTED");
if (!string.Equals(value.Mode, "LegacyConfigurationProbe", StringComparison.Ordinal)) throw new InvalidOperationException("LEGACY_PROBE_MODE_REQUIRED");
if (new[] { value.SettingsXml, value.DownloadListXml, value.CompatibilityOverlay, value.SelectedPattern, value.EvidenceOutputRoot }.Any(string.IsNullOrWhiteSpace))
throw new InvalidOperationException("LEGACY_PROBE_INPUT_MISSING");
if (new[] { value.SettingsXml, value.DownloadListXml, value.CompatibilityOverlay, value.EvidenceOutputRoot }.Any(x => Uri.TryCreate(x, UriKind.Absolute, out var uri) && !uri.IsFile || x.Contains('*') || x.Contains('?')))
throw new InvalidOperationException("LEGACY_PROBE_INPUT_PATH_INVALID");
return value;
}
catch (JsonException) { throw new InvalidOperationException("LEGACY_PROBE_OVERRIDE_UNKNOWN_FIELD"); }
}
}
@@ -49,6 +49,15 @@ public sealed class RosterAdaptersTests
Assert.Equal(["legacy-a"], selection.PluginIds); Assert.Equal(["legacy-a"], selection.PluginIds);
} }
[Fact]
public void LegacyProbeOverride_RequiresExplicitProbeModeAndStrictSchema()
{
const string valid = """{"schemaVersion":1,"mode":"LegacyConfigurationProbe","settingsXml":"C:/Settings.xml","downloadListXml":"C:/download_list.xml","compatibilityOverlay":"C:/overlay.json","selectedPattern":"Plant","evidenceOutputRoot":"C:/evidence"}""";
Assert.Equal("Plant", LegacyProbeOverrideParser.Parse(valid).SelectedPattern);
Assert.Throws<InvalidOperationException>(() => LegacyProbeOverrideParser.Parse(valid.Replace("LegacyConfigurationProbe","Production")));
Assert.Throws<InvalidOperationException>(() => LegacyProbeOverrideParser.Parse(valid[..^1] + ",\"unknown\":true}"));
}
[Fact] [Fact]
public void ProjectRoster_HasPriorityOverLegacy() public void ProjectRoster_HasPriorityOverLegacy()
{ {