Setline records training to one JSON document in the app's container. That is the only copy: lose or replace the iPhone and the history is gone, and the JSON export is the only backup. Every public surface now states this plainly, which makes it the most visible gap in the product.
Outcome
Training appears on every device signed into the same iCloud account, with no account of Setline's own, no server, and no conflict UI to think about mid-workout.
Open design decision
The original plan said SwiftData + CloudKit. Having settled the domain model, that now looks like the wrong trade: it means rewriting the value-type domain (SetlineDocument and friends) into @Model reference types, which breaks the 64 core tests that operate on structs, and it fights CloudKit's all-optional / no-unique-constraint rules.
CloudKit with per-record granularity — one record per session, template and goal, keyed by ID — reaches the identical outcome while keeping the value types and their tests intact. Sessions are append-only, so they union naturally across devices rather than conflicting.
Recommendation: per-record CloudKit. Needs a decision before implementation starts.
Scope
com.apple.developer.icloud-container-identifiers entitlement and container setup
- Per-record push and pull with a local change token; last-writer-wins on the few mutable records (templates, goals), union on append-only history
- Settings shows real iCloud state from
CKAccountStatus plus a last-merge time, replacing the current copy that says sync is "being built"
- The JSON export path keeps working throughout as the escape hatch
- Migration for documents that already exist on device, with a captured fixture test
Verification
Simulator can cover the record mapping and merge logic. Two-device convergence needs real devices signed into one iCloud account and cannot be claimed from simulator alone.
Setline records training to one JSON document in the app's container. That is the only copy: lose or replace the iPhone and the history is gone, and the JSON export is the only backup. Every public surface now states this plainly, which makes it the most visible gap in the product.
Outcome
Training appears on every device signed into the same iCloud account, with no account of Setline's own, no server, and no conflict UI to think about mid-workout.
Open design decision
The original plan said SwiftData + CloudKit. Having settled the domain model, that now looks like the wrong trade: it means rewriting the value-type domain (
SetlineDocumentand friends) into@Modelreference types, which breaks the 64 core tests that operate on structs, and it fights CloudKit's all-optional / no-unique-constraint rules.CloudKit with per-record granularity — one record per session, template and goal, keyed by ID — reaches the identical outcome while keeping the value types and their tests intact. Sessions are append-only, so they union naturally across devices rather than conflicting.
Recommendation: per-record CloudKit. Needs a decision before implementation starts.
Scope
com.apple.developer.icloud-container-identifiersentitlement and container setupCKAccountStatusplus a last-merge time, replacing the current copy that says sync is "being built"Verification
Simulator can cover the record mapping and merge logic. Two-device convergence needs real devices signed into one iCloud account and cannot be claimed from simulator alone.