fix(macos): launch service with stable privacy identity

This commit is contained in:
dh
2026-09-11 20:59:56 +02:00
parent d77187e9ec
commit 0e2aa3830f
6 changed files with 160 additions and 0 deletions
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>MeetingAssistant</string>
<key>CFBundleIdentifier</key>
<string>cloud.schweigert.meeting-assistant</string>
<key>CFBundleName</key>
<string>Meeting Assistant</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSUIElement</key>
<true/>
<key>NSCalendarsFullAccessUsageDescription</key>
<string>Meeting Assistant reads calendar metadata for meeting notes and recording prompts.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Meeting Assistant records microphone audio for live meeting transcription.</string>
</dict>
</plist>
@@ -0,0 +1,70 @@
import Darwin
import Dispatch
import Foundation
@main
private struct MeetingAssistantLauncher {
private static let serviceDirectoryName = "MeetingAssistant"
static func main() {
let runtimeDirectory = Bundle.main.bundleURL
.appendingPathComponent("Contents/Resources/app", isDirectory: true)
let assemblyPath = runtimeDirectory.appendingPathComponent("MeetingAssistant.dll").path
let environmentFile = FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Library/Application Support")
.appendingPathComponent(serviceDirectoryName)
.appendingPathComponent("config/meeting-assistant.env")
guard FileManager.default.fileExists(atPath: assemblyPath) else {
fail("Meeting Assistant runtime not found at \(assemblyPath)")
}
guard FileManager.default.fileExists(atPath: environmentFile.path) else {
fail("Meeting Assistant environment file not found at \(environmentFile.path)")
}
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/zsh")
process.arguments = [
"-c",
"set -a; source \"$1\"; set +a; exec /usr/local/share/dotnet/dotnet \"$2\" --contentRoot \"$3\"",
"meeting-assistant-launcher",
environmentFile.path,
assemblyPath,
runtimeDirectory.path
]
process.currentDirectoryURL = runtimeDirectory
signal(SIGTERM, SIG_IGN)
signal(SIGINT, SIG_IGN)
let terminationSignal = DispatchSource.makeSignalSource(signal: SIGTERM, queue: .global())
terminationSignal.setEventHandler {
if process.isRunning {
process.terminate()
}
}
terminationSignal.resume()
let interruptSignal = DispatchSource.makeSignalSource(signal: SIGINT, queue: .global())
interruptSignal.setEventHandler {
if process.isRunning {
kill(process.processIdentifier, SIGINT)
}
}
interruptSignal.resume()
do {
try process.run()
process.waitUntilExit()
Darwin.exit(process.terminationStatus)
} catch {
fail("Meeting Assistant launcher failed: \(error)")
}
}
private static func fail(_ message: String) -> Never {
FileHandle.standardError.write(Data("\(message)\n".utf8))
Darwin.exit(1)
}
}