Zwischenablage, Notizen und der Gesichtsvergleich
Drei neue Module nach dem Bauplan von `ShelfProvider`: reine Regeln getrennt vom Zustand, versionierte Indexdatei, Inhalte in Dateien statt in `UserDefaults` — was dort steht, liest jedes Programm mit `defaults read` mit. Die Zwischenablage achtet `ConcealedType`, `TransientType` und `AutoGeneratedType`. Diese Marken sind eine Verabredung zwischen Programmen und kein Systemdienst; wer sie missachtet, sammelt fremde Passwörter ein. Der Gesichtsvergleich stand im Plan als der eine echte Unsicherheitsfaktor. Ein Spike hat ihn erledigt: `VNGenerateFaceprintRequest` gibt es nicht, aber `VNGenerateImageFeaturePrintRequest` ist öffentlich, liefert 768 Elemente und ein Abstandsmaß — Faktor 3,5 Trennschärfe. Kein eigenes CoreML-Modell nötig. `FaceMatcher` entscheidet über mehrere Posen, mehrere Einzelbilder und eine Sperre nach Fehlversuchen. Die Schwelle liegt bewusst nicht mittig: ein falsches Ja ist ein Fremder am entsperrten Rechner, ein falsches Nein nur ein Passwort, das man ohnehin kennt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f289d02c37
commit
3da673662f
@@ -21,6 +21,10 @@ let package = Package(
|
||||
.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"]),
|
||||
],
|
||||
targets: [
|
||||
// Der String-Katalog muss ausdrücklich als Ressource stehen — sonst gibt
|
||||
@@ -73,8 +77,23 @@ let package = Package(
|
||||
resources: [.process("Localizable.xcstrings")]),
|
||||
.testTarget(name: "AudioProviderTests", dependencies: ["AudioProvider"]),
|
||||
|
||||
.target(name: "FaceProvider"),
|
||||
.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"]),
|
||||
]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user