Summary: - Sources: Models, Services - Docs: Proposal, README - Added symbols: extension StorageKeys, struct UserTokenKey, typealias Value, enum KeychainAccessControl, enum KeychainAccessibility, actor EncryptionHelper (+38 more) - Removed symbols: enum KeychainAccessControl, enum KeychainAccessibility, enum EncryptionConstants, func serialize, func deserialize, func applySecurity (+17 more) Stats: - 10 files changed, 1089 insertions(+), 348 deletions(-)
61 lines
2.6 KiB
Markdown
61 lines
2.6 KiB
Markdown
# LocalData Package Proposal
|
|
|
|
## Goal
|
|
Create a single, typed, discoverable namespace for persisted app data with consistent security guarantees and clear ownership. This makes it obvious what is stored, where it is stored, how it is secured, how it is serialized, who owns it, and which platforms it belongs to or should sync to.
|
|
|
|
## Package Placement
|
|
- localPackages/LocalData/
|
|
- Sources/LocalData/
|
|
- Tests/LocalDataTests/
|
|
|
|
## Dependencies
|
|
- Foundation
|
|
- Security (Keychain)
|
|
- CryptoKit (encryption)
|
|
- WatchConnectivity (sync helpers)
|
|
|
|
## Architecture
|
|
|
|
### Core Components
|
|
- **StorageKey** protocol - Defines storage configuration for each data type
|
|
- **StorageRouter** actor - Main entry point coordinating all storage operations
|
|
- **StorageProviding** protocol - Abstraction for storage operations
|
|
|
|
### Isolated Helper Classes (Actors)
|
|
Each helper is a dedicated actor providing thread-safe access to a specific storage domain:
|
|
|
|
- **KeychainHelper** - All keychain operations (set, get, delete, exists, deleteAll)
|
|
- **EncryptionHelper** - AES-256-GCM encryption with PBKDF2 key derivation
|
|
- **FileStorageHelper** - File system operations (read, write, delete, list, size)
|
|
- **UserDefaultsHelper** - UserDefaults operations with suite support
|
|
- **SyncHelper** - WatchConnectivity sync operations
|
|
|
|
### Models
|
|
- **StorageDomain** - userDefaults, keychain, fileSystem, encryptedFileSystem
|
|
- **SecurityPolicy** - none, keychain (with accessibility/accessControl), encrypted (AES-256)
|
|
- **Serializer** - JSON, property list, raw Data, or custom encode/decode
|
|
- **PlatformAvailability** - all, phoneOnly, watchOnly, phoneWithWatchSync
|
|
- **SyncPolicy** - never, manual, automaticSmall
|
|
- **KeychainAccessibility** - All 7 iOS options (whenUnlocked, afterFirstUnlock, etc.)
|
|
- **KeychainAccessControl** - All 6 options (userPresence, biometryAny, devicePasscode, etc.)
|
|
- **FileDirectory** - documents, caches, custom URL
|
|
- **StorageError** - Comprehensive error types
|
|
- **AnyCodable** - Type-erased Codable for mixed-type payloads
|
|
|
|
## Usage Pattern
|
|
Apps extend StorageKeys with their own key types and use StorageRouter.shared. This follows the Notification.Name pattern for discoverable keys.
|
|
|
|
## Sync Behavior
|
|
StorageRouter can call WCSession.updateApplicationContext for manual or automaticSmall sync policies when availability allows it. Session activation and receiving data are owned by the app.
|
|
|
|
## Platforms
|
|
- iOS 17+
|
|
- watchOS 10+
|
|
|
|
## Future Ideas (Not Implemented)
|
|
- Migration helpers for legacy storage
|
|
- Key rotation strategies for encrypted data
|
|
- Watch-optimized data representations
|
|
|
|
Any future changes should keep LocalData documentation in sync with code changes.
|