fix(macos): bundle audio capture for launchd privacy

This commit is contained in:
dh
2026-09-11 19:27:21 +02:00
parent 6adf6f726b
commit d77187e9ec
5 changed files with 65 additions and 15 deletions
@@ -16,7 +16,7 @@ namespace MeetingAssistant.Tests;
public sealed class MacOsMeetingAudioSourceTests
{
[Fact]
public void NativeMicrophoneHelperDeclaresMacOsPrivacyMetadata()
public void NativeAudioCaptureIsPackagedAsSignedMacOsAppForPersistentPrivacyGrant()
{
if (!OperatingSystem.IsMacOS())
{
@@ -25,7 +25,7 @@ public sealed class MacOsMeetingAudioSourceTests
var configuration = new DirectoryInfo(AppContext.BaseDirectory)
.Parent?.Name ?? "Debug";
var helperPath = Path.GetFullPath(Path.Combine(
var appPath = Path.GetFullPath(Path.Combine(
AppContext.BaseDirectory,
"..",
"..",
@@ -36,11 +36,30 @@ public sealed class MacOsMeetingAudioSourceTests
configuration,
"net10.0",
"Native",
"macos-meeting-audio-capture"));
var helperImage = System.Text.Encoding.UTF8.GetString(File.ReadAllBytes(helperPath));
"MeetingAssistantAudioCapture.app"));
var infoPlistPath = Path.Combine(appPath, "Contents", "Info.plist");
var helperPath = Path.Combine(appPath, "Contents", "MacOS", "macos-meeting-audio-capture");
Assert.Contains("cloud.schweigert.meeting-assistant.audio-capture", helperImage, StringComparison.Ordinal);
Assert.Contains("NSMicrophoneUsageDescription", helperImage, StringComparison.Ordinal);
Assert.True(Directory.Exists(appPath), $"Expected macOS audio capture app at '{appPath}'.");
Assert.True(File.Exists(infoPlistPath), $"Expected Info.plist at '{infoPlistPath}'.");
Assert.True(File.Exists(helperPath), $"Expected native helper at '{helperPath}'.");
var infoPlist = File.ReadAllText(infoPlistPath);
Assert.Contains("cloud.schweigert.meeting-assistant.audio-capture", infoPlist, StringComparison.Ordinal);
Assert.Contains("NSMicrophoneUsageDescription", infoPlist, StringComparison.Ordinal);
using var verification = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = "/usr/bin/codesign",
ArgumentList = { "--verify", "--deep", "--strict", appPath },
RedirectStandardError = true,
UseShellExecute = false
});
Assert.NotNull(verification);
verification.WaitForExit();
Assert.True(
verification.ExitCode == 0,
$"Expected a valid app-bundle signature: {verification.StandardError.ReadToEnd()}");
}
[Fact]