diff --git a/build/scripts/linux/build-avalonia-packages.sh b/build/scripts/linux/build-avalonia-packages.sh old mode 100644 new mode 100755 index 6a35814..8a3b868 --- a/build/scripts/linux/build-avalonia-packages.sh +++ b/build/scripts/linux/build-avalonia-packages.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" PROJECT_PATH="$REPO_ROOT/src/GregModmanager.Avalonia/GregModmanager.Avalonia.csproj" OUTPUT_ROOT="${1:-$REPO_ROOT/artifacts/avalonia-linux}" VERSION="${2:-1.1.0}" diff --git a/src/GregModmanager.Avalonia/Program.cs b/src/GregModmanager.Avalonia/Program.cs index 4a8beb4..564431f 100644 --- a/src/GregModmanager.Avalonia/Program.cs +++ b/src/GregModmanager.Avalonia/Program.cs @@ -165,6 +165,7 @@ public static IServiceProvider BuildServices() services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); diff --git a/src/GregModmanager.Core/Models/AppJsonContext.cs b/src/GregModmanager.Core/Models/AppJsonContext.cs index d7fe96d..8a3cc3c 100644 --- a/src/GregModmanager.Core/Models/AppJsonContext.cs +++ b/src/GregModmanager.Core/Models/AppJsonContext.cs @@ -34,6 +34,7 @@ namespace GregModmanager.Models; [JsonSerializable(typeof(int))] [JsonSerializable(typeof(RalphTaskStatus))] [JsonSerializable(typeof(AssetModMetadata))] +[JsonSerializable(typeof(object))] public partial class AppJsonContext : JsonSerializerContext { } diff --git a/src/GregModmanager.Core/Services/Install/DummyIntentSignatureVerifier.cs b/src/GregModmanager.Core/Services/Install/DummyIntentSignatureVerifier.cs new file mode 100644 index 0000000..798fa04 --- /dev/null +++ b/src/GregModmanager.Core/Services/Install/DummyIntentSignatureVerifier.cs @@ -0,0 +1,12 @@ +using GregModmanager.Models.Install; + +namespace GregModmanager.Services.Install; + +public class DummyIntentSignatureVerifier : IIntentSignatureVerifier +{ + public bool VerifySignature(InstallIntentContext intent) + { + // For the Vertical Slice (Phase 3), we require the signature to at least match a mock known structure. + return intent.Signature == "valid_dummy_sig" || intent.Signature.Length >= 32; + } +} diff --git a/src/GregModmanager.Core/Services/Install/IIntentSignatureVerifier.cs b/src/GregModmanager.Core/Services/Install/IIntentSignatureVerifier.cs new file mode 100644 index 0000000..0f442bf --- /dev/null +++ b/src/GregModmanager.Core/Services/Install/IIntentSignatureVerifier.cs @@ -0,0 +1,8 @@ +using GregModmanager.Models.Install; + +namespace GregModmanager.Services.Install; + +public interface IIntentSignatureVerifier +{ + bool VerifySignature(InstallIntentContext intent); +} diff --git a/src/GregModmanager.Core/Services/Install/InstallIntentClient.cs b/src/GregModmanager.Core/Services/Install/InstallIntentClient.cs index 294a3c3..9144053 100644 --- a/src/GregModmanager.Core/Services/Install/InstallIntentClient.cs +++ b/src/GregModmanager.Core/Services/Install/InstallIntentClient.cs @@ -14,9 +14,12 @@ public class InstallIntentClient : IInstallIntentClient private readonly ISessionManager _sessionManager; private readonly HashSet _consumedIntents = new(); - public InstallIntentClient(ISessionManager sessionManager) + private readonly IIntentSignatureVerifier _signatureVerifier; + + public InstallIntentClient(ISessionManager sessionManager, IIntentSignatureVerifier signatureVerifier) { - _sessionManager = sessionManager; + _sessionManager = sessionManager; + _signatureVerifier = signatureVerifier; } public async Task HandleIntentAsync(string rawUri) @@ -109,13 +112,11 @@ public async Task HandleIntentAsync(string rawUri) return Task.FromResult("Missing cryptographic signature."); } - // TODO: Implement actual cryptographic ECDSA/HMAC signature verification against server public key - // For the Vertical Slice (Phase 3), we require the signature to at least match a mock known structure. - if (intent.Signature != "valid_dummy_sig" && intent.Signature.Length < 32) - { - return Task.FromResult("Signature format invalid or unrecognized."); - } - + if (!_signatureVerifier.VerifySignature(intent)) + { + return Task.FromResult("Signature format invalid or unrecognized."); + } + return Task.FromResult(null); // Null means valid! } diff --git a/src/GregModmanager.Core/Services/TelemetryService.cs b/src/GregModmanager.Core/Services/TelemetryService.cs index 8531b66..96a7b17 100644 --- a/src/GregModmanager.Core/Services/TelemetryService.cs +++ b/src/GregModmanager.Core/Services/TelemetryService.cs @@ -99,7 +99,8 @@ public async Task TrackEventAsync(string eventName, object payload, Dictionary JsonSerializer.Serialize(sync, AppJsonContext.Default.SyncCollectionEvent), - _ => JsonSerializer.Serialize(payload, payload.GetType(), AppJsonContext.Default.Options) + string str => str, + _ => JsonSerializer.Serialize((object)payload, AppJsonContext.Default.Object) }; await PushToLokiAsync(eventName, message, labels);