feat: establish p-rec-annot composite module manifest

This commit is contained in:
codex
2026-08-07 09:06:49 +03:00
parent 91f316d79b
commit 6e909f89bc
5 changed files with 39 additions and 1 deletions
@@ -0,0 +1,27 @@
using System.Security.Cryptography;
using System.Text.Json;
namespace PRecAnnot.Plant3D2026;
internal sealed record CompositeAssemblyManifest(string Name, string Sha256, bool Required);
internal sealed record CompositeManifest(int SchemaVersion, string Package, string Version, IReadOnlyList<string> Modules, IReadOnlyList<CompositeAssemblyManifest> Assemblies);
internal static class CompositeModuleManifest
{
public static CompositeManifest Validate()
{
var assemblyPath = typeof(EntryPoint).Assembly.Location;
var path = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(assemblyPath)!, "..", "module-manifest.json"));
if (!File.Exists(path)) throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_MISSING");
var manifest = JsonSerializer.Deserialize<CompositeManifest>(File.ReadAllText(path), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_INVALID");
if (manifest.SchemaVersion != 1 || !string.Equals(manifest.Package, "P_Rec_Annot", StringComparison.Ordinal) || manifest.Modules.Count == 0) throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_INVALID");
foreach (var item in manifest.Assemblies.Where(value => value.Required))
{
var file = Path.Combine(Path.GetDirectoryName(assemblyPath)!, item.Name);
if (!File.Exists(file)) throw new InvalidOperationException($"COMPOSITE_MODULE_ASSEMBLY_MISSING:{item.Name}");
var hash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(file))).ToLowerInvariant();
if (!string.Equals(hash, item.Sha256, StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException($"COMPOSITE_MODULE_HASH_MISMATCH:{item.Name}");
}
return manifest;
}
}
@@ -15,6 +15,8 @@ public sealed class EntryPoint : IExtensionApplication
public void Initialize()
{
RuntimeDiagnostics.Write("AssemblyInitializeStarted");
var manifest = CompositeModuleManifest.Validate();
RuntimeDiagnostics.Write("CompositeModulesValidated", resultStatus: "Validated", details: new Dictionary<string, object?> { ["PackageVersion"] = manifest.Version, ["ModuleCount"] = manifest.Modules.Count });
RibbonIntegration.Register();
// Test automation is driven only by the explicitly generated /b script.
// Initialize remains production-equivalent and must not orchestrate commands.