@@ -65,7 +65,10 @@ classDiagram
6565
6666 class UserFMUDirectory
6767
68- class CacheManager
68+ class CacheManager {
69+ +get_revision_content(..., migration_manager)
70+ +restore_revision(..., migration_manager)
71+ }
6972 class LockManager {
7073 +acquire()
7174 +ensure_can_write()
@@ -75,12 +78,20 @@ classDiagram
7578 }
7679
7780 class PydanticResourceManager~PydanticResource~ {
81+ +migration_manager
7882 +load(force, store_cache)
7983 +save(model)
8084 +get_resource_diff(incoming_resource)
8185 +get_structured_model_diff(current_model, incoming_model)
8286 }
8387
88+ class MigrationManager~MigratableResource~ {
89+ +model_class
90+ +current_version: int
91+ +migrate_resource(data)
92+ +requires_backup(data)
93+ }
94+
8495 class MutablePydanticResourceManager~MutablePydanticResource~ {
8596 +get(key, default)
8697 +set(key, value)
@@ -129,6 +140,8 @@ classDiagram
129140
130141 FMUDirectoryBase *-- LockManager
131142 FMUDirectoryBase *-- CacheManager
143+ PydanticResourceManager o-- MigrationManager
144+ CacheManager ..> MigrationManager
132145 ProjectFMUDirectory *-- ProjectConfigManager
133146 ProjectFMUDirectory *-- ChangelogManager
134147 ProjectFMUDirectory *-- MappingsManager
@@ -140,10 +153,44 @@ The main library split is:
140153- ` FMUDirectoryBase ` is the filesystem-centered abstraction. It owns the ` .fmu ` path, lock manager, cache manager, and generic read/write helpers.
141154- ` ProjectFMUDirectory ` and ` UserFMUDirectory ` specialize the base class for project-local ` .fmu/ ` directories and ` $HOME/.fmu/ ` .
142155- ` PydanticResourceManager ` is the generic resource engine for loading, saving, diffing, and caching JSON-backed Pydantic models.
156+ - ` MigrationManager ` applies registered, forward-only schema migrations and validates the result as the current Pydantic model.
143157- ` MutablePydanticResourceManager ` adds dot-notation ` get ` , ` set ` , ` update ` , ` reset ` , and merge behavior for editable resources.
144158- ` ProjectConfigManager ` , ` UserConfigManager ` , ` MappingsManager ` , and ` LogManager ` bind specific Pydantic models to managed files inside ` .fmu/ ` .
145159- Directory objects compose the correct managers and delegate resource operations to them.
146160
161+ ## Schema Migration
162+
163+ ` ProjectConfig ` , ` UserConfig ` , and ` InternalMappings ` are versioned resources. Each
164+ model declares its current schema version, and each resource manager has a
165+ ` MigrationManager ` with the migration registry for that model.
166+
167+ Migration is forward-only. Data without ` schema_version ` is treated as version 1.
168+ Each registered function advances the data by one version. The manager rejects a
169+ newer schema, a missing migration step, an invalid version, or data that does not
170+ validate as the current model.
171+
172+ The migration boundary depends on the resource operation:
173+
174+ - ** Load:** ` PydanticResourceManager ` decodes the stored JSON and asks
175+ ` MigrationManager ` for a validated current model. Migration happens in memory.
176+ Loading does not write the resource, create a cache revision, or add a changelog
177+ entry.
178+ - ** Save:** The resource manager checks the write lock first. If the stored data is
179+ unversioned or older, it stores the original JSON as a normal cache revision
180+ before writing the current model. Normal cache retention applies.
181+ - ** Cache read:** ` CacheManager ` uses the migration manager to return old revisions
182+ as current validated models.
183+ - ** Restore:** ` CacheManager ` migrates the selected revision before writing it, so
184+ the restored resource uses the current schema. Project restore operations use the
185+ existing restore changelog entry.
186+
187+ There is no backward migration. After a current-schema resource is saved, an older
188+ ` fmu-settings ` release can reject it as newer than supported.
189+
190+ See the
191+ [ schema migration guide] ( src/fmu/settings/_migrations/README.md )
192+ for the implementation, test, and coordinated release process.
193+
147194## Runtime Flow
148195
149196The full runtime spans multiple repositories, but ` fmu-settings ` owns the ` .fmu/ ` directory operations used by the API and CLI.
0 commit comments