Skip to content

fix(custom-fields): guard option removals in use and revalidate default on update#41

Merged
jamofer merged 1 commit into
masterfrom
fix/custom-fields-update-options-guards
May 24, 2026
Merged

fix(custom-fields): guard option removals in use and revalidate default on update#41
jamofer merged 1 commit into
masterfrom
fix/custom-fields-update-options-guards

Conversation

@jamofer

@jamofer jamofer commented May 24, 2026

Copy link
Copy Markdown
Owner

Summary

Two silent failure modes on PUT /custom-fields/{id} get explicit errors so admins can act on them instead of corrupting downstream data.

  • Removing an option that is still in use leaves orphans. If a single_select field has value="p2" on existing bugs and the admin drops p2 from the option set, the bug rows keep p2 as a ghost — the form can't re-select it and any later PUT that omits custom_fields strips the value entirely. New helper _option_values_in_use scans the entity table (bugs / test_cases / test_executions) for stored values referencing the field key (both string and list-of-string shapes), and _guard_options_change refuses the request with 409 naming the offending values. Admins are told to migrate the values or archive the field instead.

  • Replacing the option set without revisiting the default crashes future creates. A field with required=true + default_value="p0" becomes a landmine the moment p0 leaves the options list: _apply_default_or_require stamps p0 on every new row, then validate_payload rejects it with a confusing 422 aimed at the wrong user. The same guard now revalidates default_value against the new options set on the same request, returning 422 with the offending values (single string for single_select, list of items for multi_select). Admins can either update the default in the same payload (accepted) or set it to None.

Notes:

  • The guard runs only when options is part of the update payload and the field type is single_select / multi_select. Pure metadata edits (label, required, archived) are untouched.
  • Test fixtures cover both select types, the in-use detection across both stored shapes, the happy path of "update options + default together", and explicit default_value=None to confirm clearing still works.
  • Full backend suite: 874 passing.

@jamofer jamofer merged commit c16996b into master May 24, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant