Repository navigation
fix(settings): rebase grace periods and enabled providers onto the server before saving - #1530
Conversation
…rver before saving The backend replaces grace_period_days and enabled_providers as a unit, so a tab loaded before another admin's save wrote that admin's values back. Save now re-reads the server config and overlays only the fields this tab changed, aborting the save if the read fails. The persisted grace values are shown after a save. An emptied grace field is refused (inline and on Save) instead of being saved as 7. Closes #539 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ce field Drives the real Settings page: a second config read returns another admin's AWS grace change, the user edits Azure only, and Save sends the merged map and then shows the persisted AWS value. An emptied grace field is refused with no PUT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reached
This review includes 3 billable files and costs up to $0.75.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 19 minutes for your next included review. View limit details
Comment |
|
VERDICT: REQUEST_CHANGES 3ad2c8d Findings:
Attacked:
|
rebaseMultiFieldKeys read the live form after the server read, so an edit made while the read was pending overlaid a stale value and reverted the other admin's. One predicate over the Save-time capture now drives both the changed key filter and the overlay. An unchecked provider is removed in every copy. Part of #539 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
VERDICT: APPROVE a9c47de Findings:
Prior finding (low, :3485/:3492, edits during the GET reverting server values): FIXED.
Attacked / re-run:
|
|
Independent review 2 (claude-fleet, cold): APPROVE a9c47de Findings:
Attacked:
Verified locally:
Reviewed by an independent agent with no author context (second reviewer). Review only: nothing was pushed, and the GitHub review state is unchanged. |
|
Local verification at
|
Closes #539. This is the last open part. Earlier parts landed in #570 (global keys sent only when changed), #1487 (service rows and keys) and #1495 (GCP payment repair).
Problem: the backend replaces
grace_period_daysandenabled_providersas a unit. Save sent each of them whole whenever any one of its inputs changed. So a tab opened before another admin's save wrote that admin's grace value or provider checkbox back. Separately, an emptied grace field was saved as 7 without telling the user.Change (
frontend/src/settings.ts, frontend only):GET /api/config. It callsapi.getConfig()directly, not the page cache. Then it overlays only the inputs this tab changed:global, the whole save aborts with the error toast. No config or service PUT is sent and nothing falls back to the stale value.sentFieldsagainst the snapshot). An input edited while the re-read is pending is therefore not sent, and not misjudged; it stays changed for the next Save..checkedfrom code fires no change event, so the provider sections and account loads wouldn't follow. A checkbox that differs only because another admin changed it is not marked changed, so it isn't re-sent.required: true) and on Save, instead of becoming 7.Not done here:
requiredtest, a stronger propagation test) are not part of this PR.Tests:
settings-purchasing-grace.test.ts) covers:global, with a working retry afterwards;settings.ts, 7 of the new or changed tests fail.required.settings-save-changed-fields.spec.tsdrives the real Settings page. A later config read returns another admin's AWS change, and the user edits only Azure. The PUT carries{aws: 3, azure: 5, gcp: 7}, and the AWS input then shows 3. An emptied grace field shows the toast and sends no PUT.Local (macOS, built dist):
tsc --noEmit,npm run buildand lint are clean.settings-save-changed-fields,settings-range-error-resetandpurchasing-sections, withCI=1under the shared port lock.SKIP=hadolint,actionlint,zizmor,cfn-lint, because those hooks' Python and Docker environments can't be built locally. They don't apply to these files, and CI runs them.🤖 Generated with Claude Code