Added an Updates tab to the /config page exposing the GitHub-update-channel settings in the web UI. Closes a gap that had been latent since v3.0.0: the updates.github.* config keys (master enable, poll cadence, three notification surfaces) were live in production via the channel infrastructure but had no web-UI presence — users had to edit config.yaml directly or use the raw-YAML editor to change cadence from the default monthly, toggle notification surfaces, or disable the channel entirely. v3.0.7 adds a dedicated Updates tab in /config between Notifications and Backup & Restore, with five fields covering all the channel's tunables: updates.github.enabled (master switch), updates.github.poll_interval (daily/weekly/monthly/never dropdown), updates.github.notify.banner (the in-card "vX.Y.Z is available" banner on /updates), updates.github.notify.gear_badge (the amber dot on the gear menu when an update is available), and updates.github.notify.ntfy (push notification, with helper text explicitly calling out the two-key gate with notifications.events.update_available on the Notifications tab — same pattern every ntfy event uses).
Why a new tab rather than folding into Notifications or replacing the gear menu's "Check for updates" item. Considered three reorganizations and landed on "add the tab, keep the gear menu item." The other surfaces in the app already follow a consistent split: pages for status/action, config tabs for settings. Status has /status (observe) but no Status tab in /config because Status isn't configurable; Logs has /logs (read) and a Logging tab (where retention and log level live, which ARE configurable); Notifications has no real-time page but does have a Notifications tab (config-only). Updates was the inconsistent one — it had a /updates page (real-time view: what version am I on, what's available, click Apply) but no corresponding config tab for the settings about how often that check happens and which surfaces get notified. Adding the Updates tab regularizes the pattern rather than creating a new one: the page is for acting on updates ("is there an update right now?"), the tab is for configuring the channel ("how often should it check?"). Different verbs, different surfaces. The gear menu's "Check for updates" item stays as it is.
Tab placement and naming. Inserted as the tenth of eleven tabs, between Notifications and Backup & Restore. Notifications neighbor makes sense because some of the updates-side settings (the ntfy push toggle) interact directly with notification configuration — users adjusting one will often want to adjust the other. Backup & Restore stays the last tab because it's an operational tool rather than a settings group, and it's structurally different from every other tab (it triggers actions rather than editing values). The tab is named "Updates" (singular short-form) to match the brevity of every other tab label rather than "Update channel" or "GitHub updates" — terser scans better in the tab strip and the section headers inside the tab provide the longer-form context.
Section structure within the tab. Two sections rather than one. The first ("GitHub-based update channel — discovery, polling cadence") covers the master enable plus poll_interval, framed by an intro paragraph explaining how the discovery loop works (background thread on a schedule, page loads serve cached state, "Check now" forces an immediate check regardless of cadence). The second ("Notification surfaces — where you find out about new releases") covers the three notify toggles, framed by an intro paragraph distinguishing passive surfaces (banner, badge — visible only when you visit the dashboard) from the active surface (ntfy push — pings your phone). The split keeps each section visually scannable and groups the toggles by what they conceptually mean rather than by their position in the YAML.
Live-config callout. A small dimmed panel at the bottom of the Notification surfaces section reminds users that changes here take effect within ~1 hour without a service restart, because the updates section is in LIVE_KEYS and the scheduler re-reads CONFIG on each wake. This is true for any of the five new fields — toggle the channel off, change cadence, flip a notify surface, anything — and worth saying explicitly so users don't think they need to restart after editing.
No new config keys, no schema migration, no behavior change to the channel itself. All five fields bind to keys that have existed in config.yaml.example since v3.0.0 (the channel infrastructure release) plus the v3.0.2 ntfy addition. The validator already accepts all five keys correctly. The LIVE_KEYS membership is already in place. This release is purely UI on top of unchanged underlying infrastructure. ~130-line addition to templates/config.html (one TABS entry, one section render function with two .section blocks and five field() calls); no other files touched.