Audit finding
SettingsCoordinator.Current correctly returns a defensive deep copy, but its declared type is the mutable domain model SightAdaptSettings. Consumers can change properties and collections on the returned object even though those changes are intentionally discarded unless performed inside Commit.
The behavior is safe, but the API communicates a writable current state rather than a read-only snapshot and makes accidental no-op mutation easy during future maintenance.
Target state
Make the read boundary explicit while preserving the existing transactional mutation authority in SettingsCoordinator.Commit.
Suitable options include:
- expose
IReadOnlySightAdaptSettings Current backed by a defensive snapshot; or
- replace the property with an explicitly named
CreateSnapshot() API and keep mutable settings internal to transaction callbacks.
Acceptance criteria
Audit finding
SettingsCoordinator.Currentcorrectly returns a defensive deep copy, but its declared type is the mutable domain modelSightAdaptSettings. Consumers can change properties and collections on the returned object even though those changes are intentionally discarded unless performed insideCommit.The behavior is safe, but the API communicates a writable current state rather than a read-only snapshot and makes accidental no-op mutation easy during future maintenance.
Target state
Make the read boundary explicit while preserving the existing transactional mutation authority in
SettingsCoordinator.Commit.Suitable options include:
IReadOnlySightAdaptSettings Currentbacked by a defensive snapshot; orCreateSnapshot()API and keep mutable settings internal to transaction callbacks.Acceptance criteria
SightAdaptSettingsremains available to domain mutation services only inside explicit transaction/normalization boundaries.IReadOnlySightAdaptSettingswherever mutation is not required.docs/ARCHITECTURE.md.