v2.3.0 is available. Read the upgrade guide for the current capability contracts, AI quota migration, and validation results.
Typed records in v2.3.0
CodableRecordStore<Record> accepts Identifiable, Codable, and Sendable
records. Use init(fileURL:) for persistence or init(inMemory:) for tests.
Its list, get, upsert, delete, and replaceAll methods run through the
actor. Writes encode the full collection and atomically replace the file before
changing in-memory state. Invalid files and unknown schema versions return typed
errors; they do not silently become empty stores.
Inject one instance per file through CompositionRoot. This store suits small
record sets; use the database repositories for relational queries or larger
collections. Actor isolation does not coordinate separate instances or processes.
The release fixes reloads from paths with spaces, Unicode, and percent sequences.
Full technical details in your project at
/docs/modules/Storage.mdConcurrency notes (v2.2.0)
MessageRepositoryImpl,ConversationRepositoryImpl, andSettingsRepositoryImplare@MainActor-pinned. If downstream code constructs these from a non-main actor, you need anawaitat the construction site. The public protocol API is unchanged.- Swift 6 strict concurrency across the package.
What You Get
- ✅ Repository pattern - Never expose @Model types to Views
- ✅ DTO pattern - Lightweight, Sendable data transfer objects
- ✅ Keychain wrapper - Secure, tested token storage
- ✅ Cursor pagination - Efficient infinite scroll
- ✅ Batch operations - Optimized bulk updates/deletes
- ✅ Migration framework - Safe schema evolution
- ✅ Optional cloud sync - Supabase integration (feature-flagged)
Production Setup (From Real Code)
Here’s how the boilerplate actually sets up storage inCompositionRoot.swift:
Key Architecture Decisions
- ✅ @Model types stay in the data layer - Views consume DTOs, never
@Modelobjects - ✅ DTOs are public - lightweight, Sendable structs
- ✅ Repositories on @MainActor - SwiftData requirement
- ✅ Protocol-based - easy to test with mocks
- ✅ Single ModelContext - thread-safe, no conflicts
Repository Pattern (Production Implementation)
The boilerplate uses protocol-based repositories that return lightweight DTOs:- Views never see @Model types (maintains MVVM boundaries)
- DTOs are Sendable (thread-safe)
- Easy to mock for testing
- Can swap implementations (local, cloud, hybrid)
Optional Cloud Sync
- Enable Chat Sync
- Enable Photo Sync
Sync conversations and messages across devices:Setup Guide: Chat Sync Setup
- Run SQL migration
- Enable feature flag
- Wire up hybrid repositories
- Test cross-device sync
Keychain Storage (Real Implementation)
The boilerplate includes a production-ready Keychain wrapper used for all secure storage:- ✅ iOS Security framework (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)
- ✅ Automatic PII redaction in logs
- ✅ Thread-safe operations
- ✅ Comprehensive error handling
- ✅ Works with AuthInterceptor via
KeychainTokenProvider
Customization Examples
Add New SwiftData Model
Key Files
Dependencies
- Core - Error handling, logging
- Networking - For cloud sync (optional)
Used By
- FeatureChat - Conversation and message storage
- FeatureSettings - Settings persistence
- Auth - Keychain for tokens
- App target (profile) -
ProfilePhotoStorageClientfor profile photos (optional)
Best Practices
SwiftData
SwiftData
- Use DTOs for passing data
- @MainActor for ModelContext
- Sendable for repositories
- Unique IDs with @Attribute(.unique)
Repositories
Repositories
- Protocol-based design
- Return DTOs (not @Model objects)
- Async/await throughout
- Comprehensive error handling
Cloud Sync
Cloud Sync
- Offline-first (local writes fast)
- Background sync (non-blocking)
- Graceful degradation
- Optional (feature flag)
Learn More
Full Documentation
Complete Storage guide
Chat Sync
Enable cross-device sync
Photo Storage
Enable cloud photos
Building Guide
Add custom models
Test Coverage
StorageTests runs as part of the workspace suite — 646 tests across 12 package test targets + the app test suites in one App.xctestplan pass.
Storage tests cover:
- CRUD operations
- Pagination
- Error scenarios
- Concurrent access
- Keychain operations
