Phase 9: Einrichtung, Autostart, Notarisierung — und die Mixer-Optik

Die Einrichtung beim ersten Start erklärt jede der vier Sachen einzeln und
fragt jede einzeln an. Vier Systemdialoge hintereinander wären der übliche
Weg und der falsche: wer nicht weiß wofür, klickt viermal „Nicht erlauben",
und danach fragt macOS nie wieder. Sie kommt beim ersten Start immer, auch
wenn zufällig schon alles erlaubt ist — sie erklärt auch den Helfer und den
Autostart.

Beim Autostart ist `requiresApproval` der Zustand, der weh tut. Wer das
Anmeldeobjekt in den Systemeinstellungen abgeschaltet hat, kann in Onyx auf
den Schalter drücken, so oft er will. Als „aus" angezeigt führt das in eine
Schleife, also steht dort jetzt, wo es weitergeht.

Der Mixer verliert den Schalter je Programm. Zehn Mini-Schalter untereinander
sind das, was den Eindruck macht; am Regler zu ziehen ist ohnehin die
Entscheidung, dieses Programm zu regeln, und der große Ausschalter stellt
alles zurück. Der Regler ist selbst gezeichnet — der Systemregler bringt sein
eigenes Erscheinungsbild mit und kann nicht zeigen, worauf es hier ankommt:
den Pegel und die Grenze bei 100 %.

Der Pegel wird im selben Durchlauf gemessen, in dem verstärkt wird, und über
`Atomic` weitergereicht. Eine gewöhnliche Eigenschaft wäre ein Wettlauf, eine
Sperre im Audiothread der klassische Weg zu Aussetzern. Dabei fällt das
`Date()` aus dem Echtzeitpfad, das dort nie hingehört hat.

Zwei Funde beim Bauen des Release-Wegs, beide hätten erst nach dem Hochladen
zur Ablehnung geführt: der Helfer wurde ohne sicheren Zeitstempel signiert,
und das Adapter-Framework ad-hoc. Beides gilt jetzt nur noch im Debug.
Scripts/release.sh prüft Zertifikat und Notarisierungsprofil vorweg, statt
nach zehn Minuten Bauen zu scheitern.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-08-11 10:36:26 +02:00
parent 8308536227
commit a0342205fd
19 changed files with 1589 additions and 385 deletions

View File

@@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
0B27E91E0F9BF29005B0ED64 /* SettingsWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E43384BA603C866D148D9D8 /* SettingsWindowController.swift */; };
0CEBFA01137EEED0774A089F /* FanSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F12041E330231599C6540C21 /* FanSettingsView.swift */; };
1C17FA5C3C6B3938F95B9440 /* OnboardingWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FCD3B382484AE4E9EF2F4B6 /* OnboardingWindowController.swift */; };
1E2D654EFDDF55AEA75DBB7C /* WeatherProvider in Frameworks */ = {isa = PBXBuildFile; productRef = D4578EB64F7A3372B49BC50C /* WeatherProvider */; };
2BB6AFD10DFB13FC4467BE6B /* SMCAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6DE2FA3022423D80A867C9 /* SMCAccess.swift */; };
378A5A417112CCB31EF3F774 /* OnyxNotch in Frameworks */ = {isa = PBXBuildFile; productRef = 3A32CAE6CC4D01D660F0016F /* OnyxNotch */; };
@@ -24,11 +25,13 @@
9EC9D57A96489F5578000822 /* NetworkProvider in Frameworks */ = {isa = PBXBuildFile; productRef = FF4E99C8BF0D8944C314A8AF /* NetworkProvider */; };
A529046C33E6B00C0E9508FF /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 508DECB5C05264E6130C373E /* Localizable.xcstrings */; };
A9617230F602C5D52F63A7E2 /* ShelfProvider in Frameworks */ = {isa = PBXBuildFile; productRef = FA6C9F90DF47DC0DFB9ED55D /* ShelfProvider */; };
B309DD8966B5348250CEC6BD /* LaunchAtLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41C778876BEF3D8B04F7C3C9 /* LaunchAtLogin.swift */; };
B6CD48B41866A468AE7A1BC7 /* OnyxWidgetKit in Frameworks */ = {isa = PBXBuildFile; productRef = E66577A40689DF225BCED184 /* OnyxWidgetKit */; };
C041F171FB69F4381309D978 /* AppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83C4E3CB821F903F3977E88 /* AppModel.swift */; };
C15B441081E9CCF74B52CADA /* OnyxHelperProtocol in Frameworks */ = {isa = PBXBuildFile; productRef = FBF369E2DC7BB5B1DF582630 /* OnyxHelperProtocol */; };
C1F651D2BA69358344927F26 /* MediaProvider in Frameworks */ = {isa = PBXBuildFile; productRef = 349226D70F51196CCD1C94F8 /* MediaProvider */; };
C390C5B65769A007A49C3A80 /* MetricsProvider in Frameworks */ = {isa = PBXBuildFile; productRef = 6CACA1C2A58DEFDE46F71499 /* MetricsProvider */; };
C5A4C9B4D21A951159C7D325 /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63A5510538846C8427AEB831 /* OnboardingView.swift */; };
CB75EE7C8826AC1CCAD35686 /* FanControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC3FDFD387188D36AF8287DE /* FanControl.swift */; };
CD501EBAE39807F5D354C5B2 /* OnyxMenuBar in Frameworks */ = {isa = PBXBuildFile; productRef = A7FD7A4864E5ED4B95C211AF /* OnyxMenuBar */; };
EA4D6312E8A96E177F10797F /* OnyxDesign in Frameworks */ = {isa = PBXBuildFile; productRef = 3D680DD645941493A7D3559E /* OnyxDesign */; };
@@ -49,10 +52,13 @@
055263008CB3306A8D09E6D4 /* AppIcon.icon */ = {isa = PBXFileReference; lastKnownFileType = wrapper.icon; path = AppIcon.icon; sourceTree = "<group>"; };
0804288DC4A8146DD9F3FC3E /* Onyx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Onyx.app; sourceTree = BUILT_PRODUCTS_DIR; };
24ADD22F5CE30B27020B479B /* MenuBarIcon.svg */ = {isa = PBXFileReference; path = MenuBarIcon.svg; sourceTree = "<group>"; };
41C778876BEF3D8B04F7C3C9 /* LaunchAtLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAtLogin.swift; sourceTree = "<group>"; };
45BD2DF1B775C733C8F75635 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
4D6DE2FA3022423D80A867C9 /* SMCAccess.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMCAccess.swift; sourceTree = "<group>"; };
508DECB5C05264E6130C373E /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
50A018673EE6BD9C50F1EFA0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
5FCD3B382484AE4E9EF2F4B6 /* OnboardingWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingWindowController.swift; sourceTree = "<group>"; };
63A5510538846C8427AEB831 /* OnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingView.swift; sourceTree = "<group>"; };
821B742C211265914B6CC44B /* OnyxKit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = OnyxKit; path = Packages/OnyxKit; sourceTree = SOURCE_ROOT; };
87597F09E971C14CF1E475DB /* Onyx.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Onyx.entitlements; sourceTree = "<group>"; };
8B7ECCFCBA1BAAC6583D4A39 /* OnyxHelper */ = {isa = PBXFileReference; includeInIndex = 0; path = OnyxHelper; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -149,8 +155,11 @@
FC3FDFD387188D36AF8287DE /* FanControl.swift */,
F12041E330231599C6540C21 /* FanSettingsView.swift */,
50A018673EE6BD9C50F1EFA0 /* Info.plist */,
41C778876BEF3D8B04F7C3C9 /* LaunchAtLogin.swift */,
508DECB5C05264E6130C373E /* Localizable.xcstrings */,
24ADD22F5CE30B27020B479B /* MenuBarIcon.svg */,
63A5510538846C8427AEB831 /* OnboardingView.swift */,
5FCD3B382484AE4E9EF2F4B6 /* OnboardingWindowController.swift */,
87597F09E971C14CF1E475DB /* Onyx.entitlements */,
F89CAC2A7DA89B8707D45D65 /* OnyxApp.swift */,
CB5D52C0D22AE1F5E0601AF9 /* PlaceholderWidgets.swift */,
@@ -292,7 +301,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "OUT=\"$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/Vendor\" \\\n \"$SRCROOT/Scripts/build-mediaremote-adapter.sh\"\n";
shellScript = "# Im Release mit der echten Identität signieren: ad-hoc signierte\n# Bibliotheken lehnt die Notarisierung ab.\nif [ \"$CONFIGURATION\" = \"Release\" ]; then\n export SIGN_IDENTITY=\"$EXPANDED_CODE_SIGN_IDENTITY\"\nfi\nOUT=\"$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/Vendor\" \\\n \"$SRCROOT/Scripts/build-mediaremote-adapter.sh\"\n";
};
E62FE369A03A1B8A44162F0E /* Helfer und Launchd-Plist einbetten */ = {
isa = PBXShellScriptBuildPhase;
@@ -310,7 +319,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "APP=\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH\"\nmkdir -p \"$APP/MacOS\" \"$APP/Library/LaunchDaemons\"\ncp \"$BUILT_PRODUCTS_DIR/OnyxHelper\" \"$APP/MacOS/OnyxHelper\"\ncp \"$SRCROOT/OnyxHelper/com.scarriffleservices.onyx.helper.plist\" \\\n \"$APP/Library/LaunchDaemons/\"\n# Der Helfer wird eigenständig signiert — die Signatur der App deckt\n# ihn nicht ab, und ohne gültige eigene Signatur lehnt launchd ihn ab.\n#\n# `-i` ist Pflicht: Xcode signiert Kommandozeilenprogramme sonst mit\n# dem Produktnamen (\"OnyxHelper\") als Bezeichner. Die App prüft aber\n# auf com.scarriffleservices.onyx.helper und würde ihren eigenen\n# Helfer ablehnen.\ncodesign --force --options runtime --timestamp=none \\\n -i com.scarriffleservices.onyx.helper \\\n --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" \"$APP/MacOS/OnyxHelper\"\n\n# Kein Neusignieren der App hier: Xcode signiert sie als letzten\n# Schritt, nach diesem Skript. Das repariert das Siegel von selbst\n# und legt im Debug-Build auch get-task-allow bei, ohne die im\n# Skript nachzubauen wäre — nachgemessen an der Reihenfolge im\n# Bauprotokoll (PhaseScriptExecution vor CodeSign Onyx.app).\n";
shellScript = "APP=\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH\"\nmkdir -p \"$APP/MacOS\" \"$APP/Library/LaunchDaemons\"\ncp \"$BUILT_PRODUCTS_DIR/OnyxHelper\" \"$APP/MacOS/OnyxHelper\"\ncp \"$SRCROOT/OnyxHelper/com.scarriffleservices.onyx.helper.plist\" \\\n \"$APP/Library/LaunchDaemons/\"\n# Der Helfer wird eigenständig signiert — die Signatur der App deckt\n# ihn nicht ab, und ohne gültige eigene Signatur lehnt launchd ihn ab.\n#\n# `-i` ist Pflicht: Xcode signiert Kommandozeilenprogramme sonst mit\n# dem Produktnamen (\"OnyxHelper\") als Bezeichner. Die App prüft aber\n# auf com.scarriffleservices.onyx.helper und würde ihren eigenen\n# Helfer ablehnen.\n# Zeitstempel im Release, keiner im Debug.\n#\n# Die Notarisierung verlangt einen sicheren Zeitstempel; ohne ihn\n# lehnt Apple das Paket ab, und zwar erst nach dem Hochladen. Im\n# Debug wäre er nur eine Netzanfrage bei jedem Bauen.\nif [ \"$CONFIGURATION\" = \"Release\" ]; then\n TIMESTAMP=\"--timestamp\"\nelse\n TIMESTAMP=\"--timestamp=none\"\nfi\ncodesign --force --options runtime $TIMESTAMP \\\n -i com.scarriffleservices.onyx.helper \\\n --sign \"$EXPANDED_CODE_SIGN_IDENTITY\" \"$APP/MacOS/OnyxHelper\"\n\n# Kein Neusignieren der App hier: Xcode signiert sie als letzten\n# Schritt, nach diesem Skript. Das repariert das Siegel von selbst\n# und legt im Debug-Build auch get-task-allow bei, ohne die im\n# Skript nachzubauen wäre — nachgemessen an der Reihenfolge im\n# Bauprotokoll (PhaseScriptExecution vor CodeSign Onyx.app).\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -322,6 +331,9 @@
C041F171FB69F4381309D978 /* AppModel.swift in Sources */,
CB75EE7C8826AC1CCAD35686 /* FanControl.swift in Sources */,
0CEBFA01137EEED0774A089F /* FanSettingsView.swift in Sources */,
B309DD8966B5348250CEC6BD /* LaunchAtLogin.swift in Sources */,
C5A4C9B4D21A951159C7D325 /* OnboardingView.swift in Sources */,
1C17FA5C3C6B3938F95B9440 /* OnboardingWindowController.swift in Sources */,
9C2E419014B7E04630FDF151 /* OnyxApp.swift in Sources */,
5EA873EC28C7EE21AC85A263 /* PlaceholderWidgets.swift in Sources */,
39E29ADC71D4860543AD25EB /* SettingsView.swift in Sources */,