Skip to content

Guardrails: Prevent Editing and Deleting Configs#185

Merged
Ayush8923 merged 3 commits into
mainfrom
fix/guardrails-ui-fixes
Jun 1, 2026
Merged

Guardrails: Prevent Editing and Deleting Configs#185
Ayush8923 merged 3 commits into
mainfrom
fix/guardrails-ui-fixes

Conversation

@Ayush8923
Copy link
Copy Markdown
Collaborator

@Ayush8923 Ayush8923 commented Jun 1, 2026

Issue: #180 #181

Summary:

  • Guardrail validator configs should not be editable or deletable once saved - editing them can break things downstream. This PR makes configs create-and-view only.
  • Ban list banned words are now shown in a single copyable text box with a Copy button, replacing the old pill chips.
  • Topic relevance the read-only view now displays the config's description and configuration details.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR removes config-deletion functionality and simplifies the save flow to POST-only. Saved configs display in read-only mode within the ValidatorConfigPanel. Field components gain validation (BanListModal description check), enhanced UI (BanListField clipboard copy and textarea), and read-only details display (TopicRelevanceField). Supporting types and utility functions are updated and cleaned up.

Changes

Config Save-Only and Read-Only View Mode

Layer / File(s) Summary
Type definitions and utility cleanup
app/lib/types/guardrails.ts, app/lib/utils/guardrails.ts
New BanListFieldProps, TopicRelevanceFieldProps, and related config types added. ValidatorUpdatePayload and buildValidatorUpdatePayload removed to align with save-only flow.
Read-only form UI infrastructure
app/components/guardrails/ValidatorConfigPanel.tsx, app/components/ui/MultiSelect.tsx, app/globals.css
ValidatorConfigPanel and MultiSelect add readOnly/disabled props. CSS rule .read-only-fields applies accent-based styling and not-allowed cursor to disabled form controls.
ValidatorConfigPanel read-only mode rendering
app/components/guardrails/ValidatorConfigPanel.tsx
Header shows close button, fieldset disabled, action buttons hidden when readOnly=true.
BanListField textarea and copy-to-clipboard
app/components/guardrails/BanListField.tsx
Imports shared BanListFieldProps type. Replaces word chips with auto-sizing textarea showing comma-separated banned words. Click/activate copies to clipboard and shows temporary "Copied" feedback.
TopicRelevanceField disabled read-only details display
app/components/guardrails/TopicRelevanceField.tsx
Adds disabled prop. Fetches and displays topic config description and configuration as read-only auto-sizing textareas when disabled; "New" button hidden when disabled.
BanListModal description validation
app/components/guardrails/BanListModal.tsx
Adds descriptionError state. Description must be non-empty; error displays inline with conditional border styling.
SavedConfigsList remove delete capability
app/components/guardrails/SavedConfigsList.tsx
Removes onDeleteConfig callback and delete button UI from saved config rows.
GuardrailsPage save-only workflow and read-only display
app/(main)/guardrails/page.tsx
Removes configPendingDelete state and all delete handlers. handleSaveConfig POST-only, no PATCH/update path. Selected configs display in readOnly mode. DeleteConfigModal removed. onDeleteConfig prop removed from SavedConfigsList.
TopicRelevanceModal label text update
app/components/guardrails/TopicRelevanceModal.tsx
Configuration textarea label updated to "Topic relevance Configuration *".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

bug

Suggested reviewers

  • AkhileshNegi
  • nishika26

Poem

🐰 The delete button hops away today,
Read-only configs now display,
Save-only path, so simple and light,
Clipboards copy banned words just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: preventing editing and deleting guardrails configs. It's concise, specific, and clearly reflects the primary objective of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/guardrails-ui-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Ayush8923 Ayush8923 self-assigned this Jun 1, 2026
@Ayush8923 Ayush8923 linked an issue Jun 1, 2026 that may be closed by this pull request
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/components/ui/MultiSelect.tsx (1)

67-78: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disabled state can still mutate selections when dropdown is already open.

When disabled flips to true while open, option buttons remain interactive and toggle/remove still call onChange. This breaks read-only guarantees.

Suggested fix
@@
   useEffect(() => {
+    if (disabled) {
+      setOpen(false);
+    }
+  }, [disabled]);
+
+  useEffect(() => {
     const handler = (e: MouseEvent) => {
@@
   const toggle = (opt: string) => {
+    if (disabled) return;
     if (value.includes(opt)) {
       onChange(value.filter((v) => v !== opt));
     } else {
       onChange([...value, opt]);
     }
   };
@@
   const remove = (opt: string, e: React.MouseEvent | React.KeyboardEvent) => {
+    if (disabled) return;
     e.stopPropagation();
     onChange(value.filter((v) => v !== opt));
   };
@@
                 <button
@@
-                  onClick={() => toggle(optValue)}
+                  onClick={() => !disabled && toggle(optValue)}

Also applies to: 183-209

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/ui/MultiSelect.tsx` around lines 67 - 78, The toggle and
remove handlers currently call onChange even when the component is disabled;
update the functions (toggle and remove) to early-return when the component's
disabled prop is true, e.g. if (disabled) return;, and likewise add the same
disabled guard to any inline option click/keyboard handlers (the option button
elements and the tag remove buttons referenced later around the option
rendering) so no events call onChange when disabled; also ensure you
stopPropagation and preserve accessibility attributes (aria-disabled) on those
interactive elements.
🧹 Nitpick comments (1)
app/components/guardrails/BanListField.tsx (1)

201-221: ⚡ Quick win

Use a native <button> for the copy action.

The current clickable element is a <span role="button">. Switching to <button type="button"> improves keyboard/screen-reader semantics and reduces custom key handling.

Suggested diff
-            <span
-              role="button"
-              tabIndex={0}
-              onClick={handleCopy}
-              onKeyDown={(e) => {
-                if (e.key === "Enter" || e.key === " ") {
-                  e.preventDefault();
-                  handleCopy();
-                }
-              }}
+            <button
+              type="button"
+              onClick={handleCopy}
               aria-label={copied ? "Copied" : "Copy banned words"}
               title={copied ? "Copied" : "Copy comma-separated list"}
               className="shrink-0 inline-flex items-center gap-1 px-2 py-1 rounded-md text-[11px] font-medium text-accent-primary bg-accent-primary/5 hover:bg-accent-primary/10 transition-colors cursor-pointer"
             >
               {copied ? (
                 <CheckLineIcon className="w-3 h-3 text-status-success" />
               ) : (
                 <CopyIcon className="w-3 h-3" />
               )}
               {copied ? "Copied" : "Copy"}
-            </span>
+            </button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/guardrails/BanListField.tsx` around lines 201 - 221, Replace
the interactive <span role="button"> with a native <button type="button"> to
improve accessibility: remove role and tabIndex and drop the custom onKeyDown
handler, keep the onClick={handleCopy}, aria-label and title (using copied to
toggle values), preserve the className and children (the conditional icons
CheckLineIcon / CopyIcon and the copied ? "Copied" : "Copy" text), and ensure
handleCopy and copied state/props remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/`(main)/guardrails/page.tsx:
- Around line 136-141: The POST body currently serializes only configValues when
calling guardrailsFetch; include the config name so the backend receives the
label — update the call in the guardrailsFetch request (where you build the body
for /api/guardrails/validators/configs) to merge the validated name into the
payload (e.g., combine name with configValues) so ValidatorConfigPanel's
validated name is sent and SavedConfigsList can render it.

---

Outside diff comments:
In `@app/components/ui/MultiSelect.tsx`:
- Around line 67-78: The toggle and remove handlers currently call onChange even
when the component is disabled; update the functions (toggle and remove) to
early-return when the component's disabled prop is true, e.g. if (disabled)
return;, and likewise add the same disabled guard to any inline option
click/keyboard handlers (the option button elements and the tag remove buttons
referenced later around the option rendering) so no events call onChange when
disabled; also ensure you stopPropagation and preserve accessibility attributes
(aria-disabled) on those interactive elements.

---

Nitpick comments:
In `@app/components/guardrails/BanListField.tsx`:
- Around line 201-221: Replace the interactive <span role="button"> with a
native <button type="button"> to improve accessibility: remove role and tabIndex
and drop the custom onKeyDown handler, keep the onClick={handleCopy}, aria-label
and title (using copied to toggle values), preserve the className and children
(the conditional icons CheckLineIcon / CopyIcon and the copied ? "Copied" :
"Copy" text), and ensure handleCopy and copied state/props remain unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 631652f6-784d-4365-99c7-c6eaea0ee3a6

📥 Commits

Reviewing files that changed from the base of the PR and between 4e76625 and b2cb6f3.

📒 Files selected for processing (13)
  • app/(main)/guardrails/page.tsx
  • app/api/guardrails/validators/configs/[config_id]/route.ts
  • app/components/guardrails/BanListField.tsx
  • app/components/guardrails/BanListModal.tsx
  • app/components/guardrails/DeleteConfigModal.tsx
  • app/components/guardrails/SavedConfigsList.tsx
  • app/components/guardrails/TopicRelevanceField.tsx
  • app/components/guardrails/TopicRelevanceModal.tsx
  • app/components/guardrails/ValidatorConfigPanel.tsx
  • app/components/ui/MultiSelect.tsx
  • app/globals.css
  • app/lib/types/guardrails.ts
  • app/lib/utils/guardrails.ts
💤 Files with no reviewable changes (3)
  • app/components/guardrails/DeleteConfigModal.tsx
  • app/lib/utils/guardrails.ts
  • app/api/guardrails/validators/configs/[config_id]/route.ts

Comment thread app/(main)/guardrails/page.tsx
@Ayush8923 Ayush8923 requested review from Prajna1999 and vprashrex June 1, 2026 11:32
@Ayush8923 Ayush8923 merged commit 13748be into main Jun 1, 2026
2 checks passed
@Ayush8923 Ayush8923 deleted the fix/guardrails-ui-fixes branch June 1, 2026 15:24
@Ayush8923 Ayush8923 linked an issue Jun 2, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validator Visibility: Display configurations in UI Validator: Prevent editing configs

3 participants