hoangsonww / hoangsonww/Diffuse-Native-Apps

Add schema-v2 migration path so old snapshots survive a breaking model change

Open
#4 0 comments 0 reactions 1 assignee Claimed by @hoangsonww View on GitHub
accessibility bug documentation enhancement good first issue help wanted question
Dominant language
Swift
Stars
2
Forks
0
Avg merge
1h 53m
Merged PRs (30d)
14

Description

## Motivation

Every snapshot carries `schemaVersion` (`Snapshot.swift:154`) and `SchemaVersion.current`, and ADR 0003 promises that a snapshot stays readable long after the app that wrote it. But nothing in the tree actually *acts* on that field: there is no migrator, no version branch in `SnapshotCoding`, and no test that decodes a v1 snapshot under a v2 model. The version is recorded and then ignored.

The first genuinely breaking model change — renaming a property key, changing a `PropertyValue` case, altering identity semantics — will therefore silently fail to decode, and a user's entire local history becomes unreadable. There is no cloud copy to fall back on ([ADR 0008](Documentation/adr/0008-no-cloud-sync.md)), so this is permanent data loss on a local-first product.

## Proposed Solution

Introduce a `SnapshotMigrator` in `DiffuseModels` that maps an older `SchemaVersion` payload forward to `.current` before decoding into the typed model. `SnapshotCoding.decode` reads `schemaVersion` first, runs the migration chain (v1 → v2 → …), then decodes. Migrations are pure functions over `[String: Any]`/`JSONValue`, registered in an ordered table so each new version adds one step rather than editing the decoder.

Mirror the same chain in the Kotlin engine (`Android/app/src/main/java/com/diffuse/android/domain/Models.kt`) so both families stay on the fixture contract from [ADR 0009](Documentation/adr/0009-native-android.md).

## Acceptance Criteria

- [ ] `SnapshotMigrator` exists with an ordered, testable chain keyed by `SchemaVersion`
- [ ] `SnapshotCoding.decode` reads `schemaVersion` before decoding and migrates when it is older than `.current`
- [ ] Decoding a snapshot from a *newer* schema fails with a clear, actionable error rather than a generic `DecodingError`
- [ ] A frozen v1 fixture is committed and a test proves it still decodes and diffs correctly after a synthetic v2 bump
- [ ] The Kotlin engine performs the equivalent migration, proven by `FixtureCompatibilityTest`
- [ ] `Documentation/SnapshotSchema.md` documents how to add a migration step

## Additional Context

Related: `Fixtures/snapshots/`, `Documentation/adr/0003-schema-driven-diff.md`. The golden fixtures are the natural regression net here — do not weaken them.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.