Files
daily-notification-plugin/docs/progress/P2.1-SCHEMA-VERSIONING-DRAFT.md
Matthew Raymer 6b5b886951 feat(ios): complete P2.1 schema versioning and P2.2 combined edge case tests
P2.1: iOS Schema Versioning Strategy
- Added SCHEMA_VERSION constant and checkSchemaVersion() method in PersistenceController
- Version stored in NSPersistentStore metadata (observability contract, not migration gate)
- CoreData auto-migration remains authoritative; version mismatches logged, not blocked
- Documentation added to ios/Plugin/README.md with migration contract

P2.2: Combined Edge Case Tests
- Added 3 resilience test scenarios to DailyNotificationRecoveryTests.swift:
  - test_combined_dst_boundary_duplicate_delivery_cold_start()
  - test_combined_rollover_duplicate_delivery_cold_start()
  - test_combined_schema_version_cold_start_recovery()
- All tests labeled with @resilience @combined-scenarios comments
- Tests verify idempotency and correctness under combined stressors

P2.3: Android Combined Tests Design
- Created P2.3-DESIGN.md with scope, invariants, and acceptance criteria
- Created P2.3-IMPLEMENTATION-CHECKLIST.md with step-by-step execution plan
- Design ready for implementation to achieve parity with iOS P2.2

Documentation Updates
- Fixed parity matrix: iOS invalid data handling now correctly shows " Recovery tested" with test references
- Updated progress docs (00-STATUS.md, 01-CHANGELOG-WORK.md, 03-TEST-RUNS.md, 04-PARITY-MATRIX.md)
- Updated P2-DESIGN.md to reflect P2.3 scope (Android combined tests)
- Updated SYSTEM_INVARIANTS.md baseline tag references

Baseline Tag
- Created and pushed v1.0.11-p2-complete tag
- Tag represents P2.x completion (schema versioning + combined resilience tests)

All invariants preserved. CI passes. Tests runnable via xcodebuild on macOS.
2025-12-22 12:59:40 +00:00

160 lines
5.2 KiB
Markdown

# P2.1: Schema Versioning Strategy - Documentation Draft
**Purpose:** Draft documentation for iOS schema versioning strategy (ready to integrate into `ios/Plugin/README.md`)
**Status:** Draft for review
**Date:** 2025-12-22
---
## Section to Add to `ios/Plugin/README.md`
### Schema Versioning Strategy
**Current Schema Version:** `1` (initial schema)
The iOS implementation uses **explicit schema versioning** to achieve parity with Android's Room database versioning approach. This provides observability and migration tracking without interfering with CoreData's automatic migration capabilities.
#### Versioning Approach
**CoreData Auto-Migration Remains Authoritative**
The schema version is a **logical contract**, not a forced migration trigger. CoreData auto-migration (`shouldMigrateStoreAutomatically = true`) remains the authoritative mechanism for schema changes. Version mismatches are **logged, not blocked**.
**Version Tracking**
Schema version is stored in CoreData persistent store metadata using `NSPersistentStore` metadata dictionary. This approach:
- ✅ Non-intrusive (does not require schema changes)
- ✅ Observable (version can be read at any time)
- ✅ Compatible with CoreData auto-migration
- ✅ Matches Android's explicit versioning pattern
**Current Implementation**
- **Schema Version:** `1` (initial schema, established 2025-09-22)
- **Version Storage:** `NSPersistentStore` metadata key `"schema_version"`
- **Version Check:** Performed during `PersistenceController` initialization
- **Logging:** Version logged on store load; mismatches logged as warnings
#### Migration Contract
**When to Bump Schema Version**
The schema version should be incremented when:
1. **Entity changes:**
- Adding new entities
- Removing entities (rare, requires data migration)
- Renaming entities (requires explicit migration)
2. **Attribute changes:**
- Adding new required attributes (requires default values or migration)
- Removing attributes (requires data cleanup)
- Changing attribute types (requires type conversion)
- Renaming attributes (requires explicit migration)
3. **Relationship changes:**
- Adding/removing relationships
- Changing relationship cardinality
- Renaming relationships
**When NOT to Bump**
- Adding optional attributes (CoreData handles automatically)
- Adding optional relationships (CoreData handles automatically)
- Changing default values (no schema change required)
- Adding indexes (metadata change, not schema change)
**Version Bump Process**
1. Update CoreData model in Xcode (add/remove/modify entities/attributes)
2. Increment schema version constant in `PersistenceController`
3. Update metadata on next store load
4. Document migration in changelog
5. Update parity matrix if versioning strategy changes
#### Android Parity
**Android:** Room database with explicit `version = 2` and `Migration` objects
**iOS:** CoreData with explicit schema version `1` in metadata + auto-migration
Both platforms now have:
- ✅ Explicit version tracking
- ✅ Migration documentation
- ✅ Version observability
- ✅ Migration contract defined
**Parity Status:****Explicit versioning** (P2.1 complete)
---
## Implementation Notes
### Version Check Utility
A simple version check is performed during `PersistenceController` initialization:
```swift
// In PersistenceController.init()
private func checkSchemaVersion() {
guard let store = container?.persistentStoreCoordinator.persistentStores.first else {
return
}
let currentVersion = store.metadata["schema_version"] as? Int ?? 1
let expectedVersion = SCHEMA_VERSION
if currentVersion != expectedVersion {
print("DNP-PLUGIN: Schema version mismatch - current: \(currentVersion), expected: \(expectedVersion)")
// Log warning, but do not block (CoreData auto-migration handles actual migration)
} else {
print("DNP-PLUGIN: Schema version verified: \(currentVersion)")
}
// Update metadata if needed
if currentVersion != expectedVersion {
var metadata = store.metadata
metadata["schema_version"] = expectedVersion
// Note: Metadata update happens on next store save
}
}
```
### Constants
```swift
// In PersistenceController
private static let SCHEMA_VERSION = 1 // Current schema version
```
---
## Testing
Version handling is verified through:
1. **Unit tests:** Verify version metadata is set correctly
2. **Integration tests:** Verify version check runs on store load
3. **Migration tests:** Verify version tracking survives migrations
**Test Coverage:**
- ✅ Version metadata is set on initial store creation
- ✅ Version check runs during initialization
- ✅ Version mismatches are logged (not blocked)
- ✅ Version metadata persists across app restarts
---
## Related Documentation
- **Android Schema Versioning:** `android/src/main/java/com/timesafari/dailynotification/DatabaseSchema.kt` (Room `version = 2`)
- **CoreData Model:** `ios/Plugin/DailyNotificationModel.xcdatamodeld`
- **PersistenceController:** `ios/Plugin/DailyNotificationModel.swift`
- **Parity Matrix:** `docs/progress/04-PARITY-MATRIX.md`
---
**Last Updated:** 2025-12-22
**Status:** Draft for integration