Skip to content

feat: support arbitrary TOML sections and wildcard schema keys - #4

Open
teal-bauer wants to merge 2 commits into
mainfrom
feat/arbitrary-sections-and-wildcards
Open

feat: support arbitrary TOML sections and wildcard schema keys#4
teal-bauer wants to merge 2 commits into
mainfrom
feat/arbitrary-sections-and-wildcards

Conversation

@teal-bauer

@teal-bauer teal-bauer commented Apr 20, 2026

Copy link
Copy Markdown
Member

Two related changes that unblock adding new top-level sections and shrink the schema's footprint for indexed data.

Arbitrary sections

BurntSushi/toml silently drops top-level table keys that don't match a struct field, so adding a new [profiles] or [fleet] section to /data/settings.toml made those settings vanish on every save cycle. Replace the hardcoded Config struct with map[string]map[string]interface{} so every top-level section round-trips.

As a side effect, service.go no longer needs its hardcoded-prefix warning. Replaced with schema.Has(field) so "this field isn't declared in the schema" logs come from the schema, not a literal list in code. Fields are still persisted regardless.

Wildcard schema keys

Schema keys can now contain * segments:

"dashboard.saved-locations.*.latitude": {
  "type": "float",
  "min": -90,
  "max": 90
}

Matches any single segment, so dashboard.saved-locations.42.latitude resolves the same way. Exact-match entries take precedence over patterns on collision. Parse splits entries into Settings (exact) and Patterns (wildcard) at load time so Lookup and Has stay O(1) for the common case.

Converted the five existing dashboard.saved-locations.0.* placeholder entries to .*. form, and dropped the pattern: "indexed" annotation that was standing in for the missing wildcard support.

Scope

On-disk TOML format is unchanged (still quoted flat keys like "saved-locations.0.latitude" under [dashboard]). Nested sub-tables are #3's job. Redis hash settings is unchanged; every field still lives there. Existing sections, keys, and defaults behave identically.

Test plan

  • go build ./... passes
  • go test ./... passes
  • Round-trip: arbitrary [fleet], [profiles] sections serialize to TOML and flatten back to dotted Redis keys
  • Wildcard lookup: dashboard.saved-locations.0.latitude and dashboard.saved-locations.42.latitude both match the .*.latitude schema entry
  • Deploy to deep-blue, confirm no regression in existing settings

A schema key like "dashboard.saved-locations.*.latitude" now matches any
single segment in that position, e.g. ".0.latitude", ".42.latitude".
Exact-match entries still take precedence over patterns during lookup.

Parse splits entries into Settings (exact) and Patterns (wildcards) at load
time so Has/Lookup stay O(1) for the common case.
Config is now map[string]map[string]interface{} instead of a struct with
eight named sections, so BurntSushi/toml no longer silently drops unknown
top-level sections on load. Any new [foo] section round-trips through
Redis as foo.* fields.

Replaces the hardcoded-prefix warning in service.go with a schema-based
'not in schema' warning. Fields stay persisted either way.

Converts the five indexed saved-locations schema entries from the
placeholder ".0." form to ".*." wildcards, so arbitrary indices are
recognized by the new warning logic.
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.

1 participant