Skip to content

Allow file fields on env-configured instances - #836

Merged
davidnewhall merged 5 commits into
mainfrom
fix/edit-env-instance-fields
Oct 27, 2026
Merged

davidnewhall merged 5 commits into
mainfrom
fix/edit-env-instance-fields

Conversation

@davidnewhall

@davidnewhall davidnewhall commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • An instance that exists only because of UN_* is no longer a locked card. Fields the environment owns stay disabled and are left out of the save, so the URL, API key, and other env values are not copied into the config file. Fields the environment does not set, such as a name or timeout, can be edited and are written to the file.
  • Unchanged env-only rows are still omitted from Save, so saving an unrelated setting does not create a file entry for them. Remove stays hidden on those rows because deleting the card does not remove the environment variables, and the instance comes back on the next overlay.
  • PUT of a Sonarr row that has only a name and timeout, while URL and API key stay in the environment, keeps those secrets out of the file and on the live instance.
  • Fixes item (3) on v1.0.0 Config Inconsistencies and Bugs #831
  • Probably causes more problems. 😓 Some of this is frickin complicated because we have to deal with things like lists. If a list item is set in an env var, can the config file add to it? Not very easily. Because then we have to deal with frontend and backend validators. Does the Starr instance have a url? No, but it's in the env. We don't save env vars to the config file, so we have to validate after merging the values, then save only the non-env values. sheesh. There's probably some bugs in this, and I really don't like it. But it needs to get worked out.

Test plan

  • Configure Sonarr with UN_SONARR_0_URL, UN_SONARR_0_API_KEY, and UN_SONARR_0_PATHS_0 only. The URL, key, and paths stay locked. Set a timeout and save. The timeout sticks, and the config file does not gain the URL or API key.
  • Save the page without editing that Sonarr. It does not appear as a new file entry.
  • go test -count=1 -run TestConfigPutEnvOnlySonarrAcceptsFileFields ./pkg/unpackerr/
  • golangci-lint run ./pkg/unpackerr/

Made with Cursor

davidnewhall and others added 2 commits October 26, 2026 21:33
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Some non-env-owned controls remain inaccessible, and unchanged incomplete hooks can block unrelated saves.

3 open issues
What changed in this PR

This PR lets environment-configured instances gain file-backed settings without copying environment-owned values into the config file.

Changes:

  • Enables non-env-owned fields in Starr, folder, and hook forms.
  • Omits unchanged env-only rows from saves and tracks rows that gain file settings.
  • Adds a Sonarr PUT regression test and updates row-state comments.
File Description
pkg/​unpackerr/​configput_test.go Tests saving Sonarr file fields without persisting env secrets.
frontend/​src/​pages/​settings/​StarrForm.svelte Enables file-field edits and tracks env-only row changes.
frontend/​src/​pages/​settings/​HooksForm.svelte Enables hook field edits and updates save handling.
frontend/​src/​pages/​settings/​FoldersForm.svelte Enables folder field edits and filters unchanged env-only rows.
frontend/​src/​lib/​slug.ts Updates comments describing editable env-only rows.

Review effort: Balanced

Comment thread frontend/src/pages/settings/HooksForm.svelte
Comment thread frontend/src/pages/settings/HooksForm.svelte
Comment thread frontend/src/pages/settings/StarrForm.svelte

@qwen-pr-bot qwen-pr-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed head 7f12286 against base e6cf9d7: FoldersForm.svelte, HooksForm.svelte, StarrForm.svelte, the comment fixes in slug.ts, and the new sonarr test in configput_test.go. Also read the machinery behind all three forms — env.svelte.ts, Input.svelte, hooktmpl.ts, and on the Go side configput.go, webhook.go, apps.go, hooks/validate.go, start.go.

What the diff actually is. The backend already accepted file fields on env-only instances: I ran the new TestConfigPutEnvOnlySonarrAcceptsFileFields against base and it passes there too, so it pins existing behavior rather than testing a change. Everything substantive is in the three settings forms: whole-card locking of env-only rows is gone, per-field env ownership still locks via Input's envVar/envHas, unchanged rows are omitted from the payload by comparing against the orig snapshot (which now has to be taken after mergeEnvOnlyRows, hence the moved assignments), and only persisted rows flip envOnly off. omitEnvFields keeps env values out of the file. That is the entire change, plus the #831 item-3 origin.

Executed validation. go test ./... green at head (new test included); the same test green at base. npm ci + svelte-check clean, vitest 45/45, vite build clean. All ten public CI check-runs on 7f12286 are green, including the three golangci-lint jobs I did not run locally. Beyond the suites, I built and ran the head server with UN_SONARR_0_URL/UN_SONARR_0_API_KEY env-only, a pushover env webhook, and a partial UN_WEBHOOK_1_TOKEN-only hook, and verified rendered states via DOM assertions rather than trusting the code alone:

  • Env-owned Sonarr fields render locked with the live env values; name, path, timeout, maxBytes etc. are editable. The feature works as described.
  • All three open Copilot findings below reproduce live on this build.

env-only Sonarr at head: URL and API key locked showing env values, remaining fields editable

On the three open comments from Copilot — all confirmed, and none are regressions versus base, since env-only cards were fully locked before.

  1. Incomplete env hooks block saves (HooksForm.svelte:107). Verified: validateApps warns only on ErrWebhookNoURL (apps.go), so a token-only env hook stays in the live view, its blank idField fails validation, and Save disables for the whole section. Screenshot shows exactly that: card 1 invalid, Save greyed out, while the healthy pushover hook above it could not be saved either. It is escapable — the missing URL is now an editable file field, and any successful PUT drops such leftovers via dropInvalidEnvOverlay — but given your "probably causes more problems" note I think you should make the call on purpose: keep the block, or keep skipping env-only rows in invalid the way FoldersForm effectively does through its env-aware path check.

webhooks tab at head: pushover env hook shows the default profile (no token/channel fields), token-only hook marked invalid, Save disabled

  1. Env-only hooks render the wrong profile (HooksForm.svelte:573). Confirmed live: the pushover env hook shows the default chip and no token/channel/nickname controls, so non-env extras on such hooks remain unreachable whenever TEMPLATE or URL is env-owned. If you want to close this without copying env values into the file, derive the profile from env values for env-only rows — e.g. hookFormProfile(envHas(TEMPLATE) ? envLiveValue(TEMPLATE) : hook.template, envHas(URL) ? envLiveValue(URL) : hook.url, hook.templatePath); URL sniffing alone recovers pushover/discord/slack/telegram/notifiarr.

  2. valid_ssl invisible on https env-only Starr instances (StarrForm.svelte:450). Confirmed: the .ssl-addon button does not render even though the env URL is https, because the condition reads the blank file value. One-line fix: gate on the effective URL, (envLiveValue(envField(envPrefix, slug, 'URL')) ?? app.url).startsWith('https://').

One small extra I found: omitEnvFields (slug.ts:118) uses envOwnsExact, which does not match indexed children, so saving any field on a folder configured with FOLDER_0_EXCLUDE_PATH_0 writes blank exclude_paths: [] / wait_extensions: [] into the file. No runtime impact since env still overlays, but it cuts against the PR's own "env is not copied into the file" principle; worth making envOwnsExact treat envHas-style child matches as owned.

None of this blocks approval: the diff is strictly more capable than base for env-only instances, the skip-if-unchanged and omitEnvFields invariants hold, and I found no correctness or data-loss defect in it. Approving; the notes above are yours to triage, with the ssl-toggle fix the most time-sensitive.

davidnewhall and others added 2 commits October 26, 2026 23:45
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Env-only Notifiarr hooks still hide the credential editor, and the Starr SSL toggle can misrepresent environment-controlled certificate validation.

2 open issues
3 resolved since last review

Review effort: Balanced

Comment thread frontend/src/pages/settings/HooksForm.svelte
Comment thread frontend/src/pages/settings/StarrForm.svelte
Co-authored-by: Cursor <cursoragent@cursor.com>

@qwen-pr-bot qwen-pr-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — validated, and both of Copilot's open comments reproduce on this head.

Executed: go test -count=1 ./pkg/unpackerr/ (ok, 4.8s, includes TestConfigPutEnvOnlySonarrAcceptsFileFields), npm ci + vite build for the UI, built the binary from a050f33, ran it with UN_SONARR_0_URL=https://127.0.0.1:9999, UN_SONARR_0_API_KEY=<36 chars>, UN_SONARR_0_VALID_SSL=true, and drove the settings pages in headless Chrome over CDP.

  • SSL addon (the one you asked about): the button renders because the env URL is https, but it is disabled and unchecked, aria-pressed="false", since the checkbox reads app.valid_ssl from blank(). The live config does verify certs (startup log: verify_ssl:true). Mirror what the URL field does: when envHas(…VALID_SSL), drive checked/aria from envLiveValue(…VALID_SSL) === 'true'.

    Sonarr settings row: env URL shown, SSL addon disabled and unchecked

  • Hooks comment is real too: with only UN_WEBHOOK_0_URL=https://notifiarr.com/… set, the Notifiarr profile chip appears but the dedicated key field is hidden (hookShowsApiKey reads the file URL only), and the headers editor is hidden as well, since hookShowsHeaders treats the auto-detected case as source 'default', not 'named'. The only unblock today is typing template = "notifiarr" into the file, which at least surfaces the headers editor for X-Api-Key.

Neither one can write an env-owned value to disk, omitEnvFields still strips them and the Go tests assert it, so these are display/workflow gaps in the new file-fields feature rather than data bugs. Still worth fixing before this ships: users of exactly the env-configured setups this PR targets will see their SSL validation rendered as off and have no visible way to add a Notifiarr key.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Filepath-backed environment URLs still hide editable controls, and inherited-property lookups can incorrectly mark untouched hooks as file-backed.

No open issues 🎉

3 previously missed issues

In code that hasn't changed since last review

Medium severity Use own-property checks for env-only hook detection

frontend/​src/​pages/​settings/​HooksForm.svelte:486

An unchanged env-only hook with a valid slug such as constructor is omitted from payload, but this lookup finds an inherited property and marks it as file-backed. Remove then appears, and a later Save can persist the untouched hook; use Object.hasOwn(payload, row.slug) instead. Apply the same own-property check in FoldersForm.svelte:283 and StarrForm.svelte:336.

Medium severity Resolve filepath-backed profile fields from live values

frontend/​src/​pages/​settings/​HooksForm.svelte:593

For UN_WEBHOOK_0_URL=filepath:/run/secrets/webhook-url, envLiveValue() returns the literal reference rather than the expanded URL. If that file contains a Pushover URL and no explicit template is set, the env-only row gets the Notifiarr profile and hides the editable token, channel, and nickname controls. Resolve filepath-backed profile fields from a separate snapshot of the already-fetched /live response, keeping expanded values out of the save model.

Medium severity Use effective filepath URL for SSL toggle visibility

frontend/​src/​pages/​settings/​StarrForm.svelte:486

An env-only HTTPS instance still cannot edit certificate validation when its URL comes from UN_SONARR_0_URL=filepath:/run/secrets/sonarr-url. /api/config/env retains that literal reference, so this check sees filepath: rather than the expanded https:// URL and hides the SSL toggle even when VALID_SSL is not env-owned. Use a separate effective URL from the already-fetched /live data for this visibility check without copying it into the file payload.

2 resolved since last review

Review effort: Balanced

@davidnewhall
davidnewhall merged commit 5dd4b37 into main Oct 27, 2026
11 checks passed
@davidnewhall
davidnewhall deleted the fix/edit-env-instance-fields branch October 27, 2026 07:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants