Files
onyx/Spikes/appgroup-probe.swift
Guido Schmit 41ee3cc174 Phase 0: Repo-Gerüst und vier Verifikations-Spikes
Vier Annahmen des Plans vor jedem Implementierungscode geprüft:

A (SMC):  Lüftersteuerung bestätigt — F0md/F1md (klein!) als Auto/Manuell-
          Umschalter, F0Tg als Ziel, Grenzen aus F0Mn/F0Mx. SMC-Integer sind
          little-endian, nicht big-endian wie im verbreiteten Intel-Beispielcode.
          Ladelimit: CHWA/CH0B/CH0C/bfE0/bfF0 existieren auf Mac17,9 nicht.
          Key noch nicht identifiziert, deshalb smc-diff.sh für eine
          Differenzmessung ohne jeden Schreibzugriff.
B (Media): mediaremote-adapter läuft unter 26.6.1, aus dem Quellcode gebaut.
          Liefert vollständige Metadaten inkl. Cover aus Google Chrome — der
          Fall, den AppleScript nicht erreicht.
C (Audio): Process Tap + privates Aggregate-Device liefern echte Samples
          (469 Callbacks/5 s, 0 stille Puffer). Konflikt gefunden: SoundSource
          6.1.1 mit ARK.driver ist bereits installiert.
D (Group): App-Group-Container ist aus einem nicht-sandboxed Prozess erreichbar.
          Damit trägt die Sandbox-Entscheidung, die Bridge-App entfällt.

Spikes sind Wegwerfcode zur Verifikation, kein Produktionscode.
2026-08-10 16:47:54 +02:00

61 lines
2.6 KiB
Swift

// Spike D App-Group-Container aus einem NICHT sandboxed Prozess
//
// Frage: liefert containerURL(forSecurityApplicationGroupIdentifier:) einen Pfad,
// wenn der Prozess die App-Group-Entitlement trägt, aber NICHT sandboxed ist?
// Davon hängt ab, ob Onyx den Calendarr-Snapshot direkt lesen kann oder eine
// sandboxed Bridge-App braucht.
//
// Bauen und signieren: Spikes/build-appgroup-probe.sh
import Foundation
let groupID = "PP34X97WS3.group.com.scarriffleservices.calendarr"
print("App-Group-Probe")
print("Gruppe: \(groupID)")
print("Sandboxed: \(ProcessInfo.processInfo.environment["APP_SANDBOX_CONTAINER_ID"] != nil ? "ja" : "nein")")
print(String(repeating: "", count: 64))
guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupID) else {
print("ERGEBNIS: nil")
print()
print("Der Container ist nicht erreichbar. Mögliche Ursachen:")
print(" 1. Entitlement fehlt oder Signatur ungültig")
print(" 2. Team-Präfix stimmt nicht byte-genau")
print(" 3. App-Group ohne Sandbox wird doch nicht gewährt → Bridge-App nötig")
exit(1)
}
print("ERGEBNIS: \(url.path)")
print("Existiert: \(FileManager.default.fileExists(atPath: url.path) ? "ja" : "nein (Calendarr lief hier noch nie)")")
// Schreibprobe der Container muss beschreibbar sein, sonst wäre selbst ein
// eigener Cache dort unmöglich. Berührt widget-cache.json NICHT.
let probe = url.appendingPathComponent(".onyx-probe")
do {
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
try Data("ok".utf8).write(to: probe)
try FileManager.default.removeItem(at: probe)
print("Schreibzugriff: ja")
} catch {
print("Schreibzugriff: nein (\(error.localizedDescription))")
}
// Was liegt drin? Nur auflisten, nichts öffnen und nichts verändern.
if let items = try? FileManager.default.contentsOfDirectory(atPath: url.path), !items.isEmpty {
print("\nInhalt:")
for item in items.sorted() { print(" \(item)") }
} else {
print("\nContainer ist leer — Calendarr-Mac-App noch nicht gestartet.")
print("Das ist der Zustand .neverWritten, den das Kalender-Widget anzeigen muss.")
}
// Die Darwin-Notification, auf die Onyx später hört. Nur registrieren, um zu
// bestätigen, dass das ohne Sandbox funktioniert.
let name = "com.scarriffleservices.calendarr.snapshot-changed"
CFNotificationCenterAddObserver(
CFNotificationCenterGetDarwinNotifyCenter(), nil,
{ _, _, _, _, _ in print("Darwin-Notification empfangen") },
name as CFString, nil, .deliverImmediately)
print("\nDarwin-Observer für '\(name)' registriert (ohne Fehler).")