Kameraaufnahme, Anlernen über drei Posen, Fenster je Bildschirm auf Bildschirmschoner-Ebene, Passwortrückfall. **Das Anmeldepasswort wird nicht gespeichert.** Ein Spike hat den Weg freigeräumt: `ODRecord.verifyPassword` ist öffentliche API, die Eingabe geht direkt hinein, das Ergebnis ist ein `Bool`, danach ist die Zeichenkette wieder weg. Damit fällt der Grund weg, aus dem vergleichbare Programme sich das Passwort geben lassen und in die Keychain legen. Angelernt wird über drei Posen mit je fünf Aufnahmen. Der Merkmalsvektor ist ein allgemeiner Bildmerkmalsvektor und kein Gesichtsmerkmal — er reagiert auf Kopfhaltung und Beleuchtung mit. Eine einzige Aufnahme beschreibt genau eine Haltung bei genau einem Licht. Die Vektoren liegen in der Keychain, nicht in einer Datei: aus ihnen lässt sich kein Bild zurückgewinnen, aber wer sie hat, kann prüfen, ob eine bestimmte Person vor der Kamera stand. Die Einschränkung steht auf dem Sperrbildschirm selbst und nicht im Kleingedruckten: Bequemlichkeit, keine Sicherheitsgrenze; der Vergleich läuft über die Webcam und lässt sich mit einem Foto täuschen. Wer sich darauf verlässt, tut es dort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
104 lines
5.6 KiB
Swift
104 lines
5.6 KiB
Swift
// swift-tools-version: 6.2
|
|
import PackageDescription
|
|
|
|
let package = Package(
|
|
name: "OnyxKit",
|
|
// Quellsprache ist Englisch, damit die Schlüssel im Code lesbar bleiben.
|
|
// Deutsch kommt als Übersetzung dazu; die Systemsprache entscheidet.
|
|
defaultLocalization: "en",
|
|
platforms: [.macOS(.v26)],
|
|
products: [
|
|
.library(name: "OnyxCore", targets: ["OnyxCore"]),
|
|
.library(name: "OnyxHelperProtocol", targets: ["OnyxHelperProtocol"]),
|
|
.library(name: "OnyxDesign", targets: ["OnyxDesign"]),
|
|
.library(name: "OnyxNotch", targets: ["OnyxNotch"]),
|
|
.library(name: "OnyxWidgetKit", targets: ["OnyxWidgetKit"]),
|
|
.library(name: "OnyxMenuBar", targets: ["OnyxMenuBar"]),
|
|
.library(name: "CalendarProvider", targets: ["CalendarProvider"]),
|
|
.library(name: "WeatherProvider", targets: ["WeatherProvider"]),
|
|
.library(name: "MediaProvider", targets: ["MediaProvider"]),
|
|
.library(name: "MetricsProvider", targets: ["MetricsProvider"]),
|
|
.library(name: "NetworkProvider", targets: ["NetworkProvider"]),
|
|
.library(name: "AudioProvider", targets: ["AudioProvider"]),
|
|
.library(name: "ShelfProvider", targets: ["ShelfProvider"]),
|
|
.library(name: "ActivityProvider", targets: ["ActivityProvider"]),
|
|
.library(name: "ClipboardProvider", targets: ["ClipboardProvider"]),
|
|
.library(name: "NotesProvider", targets: ["NotesProvider"]),
|
|
.library(name: "FaceProvider", targets: ["FaceProvider"]),
|
|
.library(name: "LockProvider", targets: ["LockProvider"]),
|
|
],
|
|
targets: [
|
|
// Der String-Katalog muss ausdrücklich als Ressource stehen — sonst gibt
|
|
// es kein `Bundle.module`, und die Übersetzungen wären zur Laufzeit
|
|
// unauffindbar.
|
|
.target(name: "OnyxCore", resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "OnyxCoreTests", dependencies: ["OnyxCore"]),
|
|
|
|
// Geteilt zwischen App und privilegiertem Helfer — deshalb ohne jede
|
|
// Abhängigkeit: der Helfer läuft als root und soll so wenig Code wie
|
|
// möglich enthalten.
|
|
.target(name: "OnyxHelperProtocol"),
|
|
.testTarget(name: "OnyxHelperProtocolTests", dependencies: ["OnyxHelperProtocol"]),
|
|
|
|
.target(name: "OnyxDesign"),
|
|
|
|
.target(name: "OnyxNotch", dependencies: ["OnyxDesign"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "OnyxNotchTests", dependencies: ["OnyxNotch"]),
|
|
|
|
.testTarget(name: "OnyxDesignTests", dependencies: ["OnyxDesign"]),
|
|
|
|
.target(name: "OnyxWidgetKit", dependencies: ["OnyxDesign"]),
|
|
.testTarget(name: "OnyxWidgetKitTests", dependencies: ["OnyxWidgetKit"]),
|
|
|
|
.target(name: "OnyxMenuBar", dependencies: ["OnyxDesign", "OnyxWidgetKit"]),
|
|
.testTarget(name: "OnyxMenuBarTests", dependencies: ["OnyxMenuBar"]),
|
|
|
|
.target(name: "CalendarProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "CalendarProviderTests", dependencies: ["CalendarProvider"]),
|
|
|
|
.target(name: "WeatherProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "WeatherProviderTests", dependencies: ["WeatherProvider"]),
|
|
|
|
.target(name: "MediaProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "MediaProviderTests", dependencies: ["MediaProvider"]),
|
|
|
|
.target(name: "MetricsProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit", "OnyxMenuBar", "OnyxHelperProtocol"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "MetricsProviderTests", dependencies: ["MetricsProvider"]),
|
|
|
|
.target(name: "NetworkProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit", "OnyxMenuBar", "MetricsProvider"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "NetworkProviderTests", dependencies: ["NetworkProvider"]),
|
|
|
|
.target(name: "AudioProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "AudioProviderTests", dependencies: ["AudioProvider"]),
|
|
|
|
.target(name: "FaceProvider",
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.target(name: "LockProvider", dependencies: ["OnyxDesign", "FaceProvider"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "FaceProviderTests", dependencies: ["FaceProvider"]),
|
|
|
|
.target(name: "NotesProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "NotesProviderTests", dependencies: ["NotesProvider"]),
|
|
|
|
.target(name: "ClipboardProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
.testTarget(name: "ClipboardProviderTests", dependencies: ["ClipboardProvider"]),
|
|
|
|
.target(name: "ShelfProvider", dependencies: ["OnyxDesign", "OnyxWidgetKit"],
|
|
resources: [.process("Localizable.xcstrings")]),
|
|
// Live Activities: die Warteschlange ist reine Rechnung ohne AppKit,
|
|
// die Darstellung hängt am Notch-Panel.
|
|
.target(name: "ActivityProvider", dependencies: ["OnyxDesign", "OnyxNotch"]),
|
|
.testTarget(name: "ShelfProviderTests", dependencies: ["ShelfProvider"]),
|
|
.testTarget(name: "ActivityProviderTests", dependencies: ["ActivityProvider"]),
|
|
]
|
|
)
|