- Add DnsmasqConfKeys for DHCP advanced, DHCPv6/RA, TFTP/PXE, DNSSEC, Other
- Add EffectiveDnsmasqConfig + EffectiveConfigSources for new options
- Wire ConfigSetCache BuildEffectiveConfig/Sources/CreateDefault
- Add EffectiveConfigFieldBuilder sections (TFTP/PXE, DNSSEC), tooltips, registry
- Update EffectiveDnsmasqConfigTests CreateConfig with all new params
- Add one parser test per conf option with documented example (200 tests)
- Replace FieldBounds with generic ClientSettingsField<T> abstraction
- Add IClientSettingsField, ClientSettingsMinMaxField, ClientSettingsBoolField
- Put abstractions in Models/Client/Abstractions namespace
- Fields hold values; CoerceValue for clamping on set
- ClientSettingsService hydrates fields on load; ToDto for save
- Settings modal binds directly to field values, collapsible only for All context
- Add LogsPreView with ShouldRender freeze to prevent Blazor overwriting JS-owned logs DOM
- Add left margin to static group heading in single-section mode
- Add app version to sidebar footer with link to GitHub release
- CSS cache busting: append version query string to static assets
- Remove LogEvents; improve startup logging with version, env, paths, uptime
- Settings modal: collapsible groups with search-aware expand/collapse
- Release workflow and publish script: pass version from tag for builds
- Move Client/Http, Services, Parsers under Infrastructure/ (Client, Services, Parsers)
- Move config helpers (DnsmasqConfKeys, DnsmasqOptionTooltips, DnsmasqFileEncoding, EffectiveConfigFieldBuilder) to Infrastructure/Helpers/Config; ApiJsonOptions to Helpers/Http
- Move Configuration types (ApplicationOptions, DnsmasqOptions, DnsmasqOptionsValidator) to Models/Config
- Merge Models/Status and Models/EffectiveConfig into Models/Dnsmasq and Models/Dnsmasq/EffectiveConfig
- Move Client/Models and Client/Services to Models/Client and Infrastructure/Services
- Move ConfigSetSnapshot, HostsSnapshot, ProcessRunResult, ManagedConfigContent from Infrastructure/Services/Abstractions to Models/Contracts
- Update all namespaces and usings; tests pass
- EnsureManagedConfigHostedService: write conf-file=/absolute/path so
dnsmasq finds the managed file regardless of CWD (e.g. systemd with CWD=/)
- Dnsmasq.razor: show Config files (load order) as single list with all
paths (main, conf-dir, managed); fallback to Main/Managed when set unavailable
- Add DnsmasqFileEncoding.Utf8NoBom for all config and hosts file writes
- Strip BOM from first line when reading main config and managed config
- Prevents 'bad option at line 1' when dnsmasq loads files written by the app
- Config set cache: ConfigSetCache, IConfigSetCache, ConfigSetSnapshot. One read of
main + conf-dir + managed config, build snapshot via parser pathToLines overloads.
Watchers (main + managed file), 120s staleness, Invalidate(), NotifyWeWroteManagedConfig.
- Parser: use DnsmasqConfKeys in DnsmasqConfIncludeParser and ConfigSetCache; add
DnsmasqConfKeys.cs and use in DnsmasqConfOptionRegistry.
- ConfigSetSnapshot: add DhcpHostEntries (built from pathToLines). ReadDhcpHostsAsync
and ReadManagedConfigAsync use cache; writes call NotifyWeWroteManagedConfig.
- DnsmasqConfigSetService: use IConfigSetCache only; all data from snapshot.
- Hosts cache: HostsCache, IHostsCache, HostsSnapshot (managed + read-only). Watchers
on managed and system hosts path, staleness, NotifyWeWroteManagedHosts.
- HostsFileService and HostsController: use IHostsCache for ReadAsync and GetReadOnly.
- Tests: DnsmasqConfigSetServiceTests use ConfigSetCache with test options.
- Managed hosts file (zz-dnsmasq-webui.hosts): app reads/writes only this;
addn-hosts in managed config loads it. SystemHostsPath is read-only display.
- Hosts page: editable managed file; then 'Other hosts (read-only)' (system
hosts when configured and !no-hosts, plus addn-hosts excluding managed).
- GET api/hosts/readonly for read-only files; no-hosts hides system hosts.
- HostsFileSection.razor component; fix space before read-only badge.
- Test harness: show container /etc/hosts (default SystemHostsPath).
- Config parsing/sources, tests and client updates for new hosts model.
- Static hosts: read dhcp-host from all config files; show external as read-only
with Source column; IsEditable + SourcePath on DhcpHostEntry; reject save if
managed entry duplicates MAC from another file (400 + message)
- Lease field: single input + datalist (type or select), remove Other dropdown
- MAC field: single input + datalist from current leases, TryFillFromLeaseByMac
- Add host: default Name=*, suggest next free IP from DHCP range
- Leases: configurable refresh polling; Settings modal for interval (client-side)
- DhcpHostsClient: surface 400 error body message on save failure
- App title config (ApplicationOptions), nav/layout/error/hosts tweaks