Skip to content

Add schema-version consistency to persisted formats that lacked it - #238

Merged
foxly-it merged 1 commit into
mainfrom
feat/schema-version-consistency
Aug 13, 2026
Merged

Add schema-version consistency to persisted formats that lacked it#238
foxly-it merged 1 commit into
mainfrom
feat/schema-version-consistency

Conversation

@foxly-it

Copy link
Copy Markdown
Owner

Closes #237.

Summary

Scoped deliberately, per explicit user direction, to schema-version + fail-closed consistency rather than a full transform-function migration framework - RootGuard doesn't yet have a real breaking-schema-change history that would justify one.

Every persisted JSON file across rootguard-core/rootguard-updater was audited (status.json ×3, images.json, backup-settings.json, sessions.json, credentials.json, audit.json, and both already-versioned formats). Most already have adequate cheap validity checks and low-consequence failure modes on a shape mismatch (re-run a step, lose a log entry) - adding versioning there would be ceremony, not a real improvement. Two genuine gaps closed:

  • updater/backups.go's per-backup manifest.json - the direct sibling of backupexport.Manifest (which already has SchemaVersion), but authorizes restoring files into a live container during rollback without one. Now checked (backupManifestSchemaVersion) before both retention-scan trust (validBackupManifest) and rollback restore (verifyBackupManifest).
  • unbound/settings.go's settings.json - the most complex, most frequently evolving persisted format, with an existing hand-rolled additive-field migration story (jsonFieldExists) that a naive "reject on any mismatch" would have conflicted with. Gets a schema_version envelope (persistedSettings) kept deliberately off the Settings type itself - which is also the guided-settings HTTP API response shape, so a persistence concern shouldn't leak into it. Load refuses only a newer version than the build knows (the genuinely dangerous case: fields repurposed with a different meaning); an absent or older version still flows through the existing additive-field defaulting unchanged.

Test plan

  • go build ./..., go vet ./..., go test ./... (rootguard-core)
  • Existing TestLoadMigratesGuidedControls (the pre-existing additive-migration regression test) passes unmodified against a genuinely old, pre-versioning fixture
  • New tests: TestVerifyBackupManifestRejectsUnsupportedSchemaVersion, TestLoadReadsSchemaVersionedSettings (round-trip), TestLoadRefusesNewerSchemaVersion

@foxly-it
foxly-it force-pushed the feat/schema-version-consistency branch from a20aeaf to fcb8d42 Compare August 13, 2026 16:45
)

Scoped deliberately to schema-version + fail-closed consistency rather
than a full transform-function migration framework, per explicit user
direction - RootGuard doesn't yet have a real breaking-schema-change
history that would justify one.

Every persisted JSON file across rootguard-core/rootguard-updater was
audited. Most already had adequate cheap validity checks and
low-consequence failure modes on a shape mismatch; adding versioning there
would have been ceremony. Two genuine gaps:

- updater/backups.go's per-backup manifest.json - the direct sibling of
  backupexport.Manifest, which already has SchemaVersion, but authorizes
  restoring files into a live container during rollback without one. Now
  checked before both retention-scan trust and rollback restore.
- unbound/settings.go's settings.json - the most complex, most frequently
  evolving persisted format, with an existing hand-rolled additive-field
  migration story (jsonFieldExists) a naive "reject on any mismatch" would
  have conflicted with. Gets a schema_version envelope kept deliberately
  off the Settings type itself (also the guided-settings HTTP API response
  shape - a persistence concern shouldn't leak into that). Load refuses
  only a *newer* version than the build knows; an absent or older version
  still flows through the existing additive defaulting unchanged, and its
  existing test (TestLoadMigratesGuidedControls) passes unmodified.
@foxly-it
foxly-it force-pushed the feat/schema-version-consistency branch from fcb8d42 to 7dd5f9b Compare August 13, 2026 17:11
@foxly-it
foxly-it merged commit 0bd57fd into main Aug 13, 2026
13 checks passed
@foxly-it
foxly-it deleted the feat/schema-version-consistency branch August 13, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migration framework for persistent state and configuration schemas

1 participant