Any admin Save silently resets peeringEnabled (and other non-form settings) — saveSettings PUTs a partial object #306

Closed
opened 2026-08-21 16:57:14 +00:00 by Cordy · 2 comments
Owner

Dogfood finding (2026-08-21, Nikola): "global peering on the Bao instance always turns off upon redeployment and the files instance does not."

Diagnosis: not the redeploy. PUT /api/v1/settings has documented REPLACE semantics; the frontend saveSettings() builds its body by hand from the admin form fields only — peeringEnabled, peeringExpandGroups, peeringMaxFileBytes, peeringBaseUrl are absent, decode as zero values, and get persisted as such. So every admin Save (basic/sharing/storage/retention/trash/audit) turns peering off. Redeploys correlate because each release's dogfood checklist includes an admin Save on bao; enc kept its toggle only because nothing was saved there since peering was enabled. The peering panel's own toggle already does it right (Object.assign({}, serverSettings, {...})) — #134's pattern never reached the older saveSettings.

Persistence itself is healthy: both instances run state-in-backend (#153), settings write through statestore encrypted to the bucket, and the boot gate is a live closure on settingsStore.Get().PeeringEnabled.

Fix: saveSettings merges its form fields over serverSettings (JSON.stringify(Object.assign({}, serverSettings, {...}))), preserving every field the form doesn't own — including any future settings fields, which makes this a one-time fix for the whole class.

Known residual (accepted): two admins saving concurrently can still lose each other's changes (last-writer-wins on the full object) — inherent to #52's replace semantics, fine for the beta.

**Dogfood finding (2026-08-21, Nikola):** "global peering on the Bao instance always turns off upon redeployment and the files instance does not." **Diagnosis:** not the redeploy. `PUT /api/v1/settings` has documented REPLACE semantics; the frontend `saveSettings()` builds its body by hand from the admin form fields only — `peeringEnabled`, `peeringExpandGroups`, `peeringMaxFileBytes`, `peeringBaseUrl` are absent, decode as zero values, and get persisted as such. So **every admin Save** (basic/sharing/storage/retention/trash/audit) turns peering off. Redeploys correlate because each release's dogfood checklist includes an admin Save on bao; enc kept its toggle only because nothing was saved there since peering was enabled. The peering panel's own toggle already does it right (`Object.assign({}, serverSettings, {...})`) — #134's pattern never reached the older `saveSettings`. Persistence itself is healthy: both instances run state-in-backend (#153), settings write through `statestore` encrypted to the bucket, and the boot gate is a live closure on `settingsStore.Get().PeeringEnabled`. **Fix:** `saveSettings` merges its form fields over `serverSettings` (`JSON.stringify(Object.assign({}, serverSettings, {...}))`), preserving every field the form doesn't own — including any future settings fields, which makes this a one-time fix for the whole class. **Known residual (accepted):** two admins saving concurrently can still lose each other's changes (last-writer-wins on the full object) — inherent to #52's replace semantics, fine for the beta.
Author
Owner

Hotfix shipped as v0.6.62 (PR #307), live on both dogfoods.

saveSettings now sends Object.assign({}, serverSettings, { …form fields… }) — the same merge pattern the peering toggle already used — so any field the admin forms don't own (peering enable, group expansion, transfer cap, base URL, and whatever we add later) survives every Save.

Dogfood checklist (bao is the good testbed):

  • Enable global peering in the Instance-peering panel
  • Save something unrelated in another admin panel (e.g. storage limits or instance name)
  • Peering is STILL on (pre-fix this was the exact reset trigger)
  • Redeploy-equivalent check: after the next release roll, peering stays on
  • Enable "expand group receivers" too, save elsewhere again → both flags survive
  • The saved panel's own values still persist correctly (no regression)

One note from the diagnosis worth keeping in mind: the resets you saw "on redeployment" were actually caused by the admin Saves in each release's checklist — the redeploy itself never touched settings, and state-in-backend (#153) was persisting everything it was given correctly on both instances.

Hotfix shipped as **v0.6.62** (PR #307), live on both dogfoods. `saveSettings` now sends `Object.assign({}, serverSettings, { …form fields… })` — the same merge pattern the peering toggle already used — so any field the admin forms don't own (peering enable, group expansion, transfer cap, base URL, and whatever we add later) survives every Save. **Dogfood checklist (bao is the good testbed):** - [x] Enable global peering in the Instance-peering panel - [x] Save something unrelated in another admin panel (e.g. storage limits or instance name) - [x] Peering is STILL on (pre-fix this was the exact reset trigger) - [x] Redeploy-equivalent check: after the next release roll, peering stays on - [x] Enable "expand group receivers" too, save elsewhere again → both flags survive - [x] The saved panel's own values still persist correctly (no regression) One note from the diagnosis worth keeping in mind: the resets you saw "on redeployment" were actually caused by the admin Saves in each release's checklist — the redeploy itself never touched settings, and state-in-backend (#153) was persisting everything it was given correctly on both instances.
Author
Owner

fixed

fixed
Cordy closed this issue 2026-08-27 00:54:16 +00:00
Sign in to join this conversation.
No labels
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#306
No description provided.