Skip to content

feat(studio): create duplicate guardrail - #1157

Merged
aray12 merged 13 commits into
mainfrom
astd-341-guardrails-duplicate
Aug 10, 2026
Merged

feat(studio): create duplicate guardrail #1157
aray12 merged 13 commits into
mainfrom
astd-341-guardrails-duplicate

Conversation

@aray12

@aray12 aray12 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor
Screen.Recording.2026-08-07.at.2.48.41.PM.mov

Summary by CodeRabbit

New Features

  • Added options to duplicate guardrail configurations from list and detail views.
  • Duplication opens a pre-filled creation form with the original description and data.
  • Automatically generates an editable “-copy” name, including support for maximum-length names.
  • Added distinct duplicate-mode titles and navigation behavior.
  • Standardized copy naming for data designer jobs.

Tests

  • Added coverage for duplicate defaults, form submission, navigation, closing behavior, and copy-name handling.

aray12 added 8 commits August 5, 2026 15:25
Adds a "Create Guardrail" button to the guardrails list header that
navigates to /guardrails/new, where a modal lets the user name the
guardrail and POST it to the API before redirecting to the detail route.

Client-side validation matches the backend name pattern
(^[a-z](?!.*--)[a-z0-9\-@.+_]{1,62}(?<!-)$) so invalid names are
caught before the API is called. Input attributes suppress browser
autocomplete and autocorrect for the identifier field.

Signed-off-by: Alex Ray <alray@nvidia.com>
- Rename body to input in POST mock handler to avoid shadowing the PATCH
  handler's body variable in the same file scope
- Add disabled={isPending} to FormModal so the user cannot close or
  resubmit the modal while the create request is in flight

Signed-off-by: Alex Ray <alray@nvidia.com>
Avoids a naming conflict where a guardrail named 'new' would be
unreachable via the UI. The ~ character is outside the backend name
pattern so /~new can never collide with a real guardrail name.

Signed-off-by: Alex Ray <alray@nvidia.com>
Drops the /~new sub-path entirely. The creation modal is now opened by
local state in GuardrailsRoute rather than a child route, so there is no
URL segment that can collide with a guardrail name and no history entry
to skip past when navigating back from the detail page.

Moves the component to GuardrailsRoute/CreateGuardrailModal, matching
the CreateSecretModal placement under SecretsListRoute.

Signed-off-by: Alex Ray <alray@nvidia.com>
…ection

react-hook-form re-throws from its submit handler and FormModal drops the
returned promise, so a rejected POST surfaced as an unhandled rejection.
The user already saw the failure via errorText, but the rejection escaped
and turned the test run red. Catch it and return, matching CreateSecretModal.

Also renames the zod schema to createGuardrailFormSchema to match the
naming used by sibling form modals, and adds tests covering the success
path, the failed-create path, and client-side name validation.

Signed-off-by: Alex Ray <alray@nvidia.com>
Signed-off-by: Alex Ray <alray@nvidia.com>
…reation-flow

Signed-off-by: Alex Ray <alray@nvidia.com>
Signed-off-by: Alex Ray <alray@nvidia.com>
@aray12
aray12 requested review from a team as code owners August 7, 2026 01:50
@github-actions github-actions Bot added the feat label Aug 7, 2026
…reation-flow

Signed-off-by: Alex Ray <alray@nvidia.com>
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

…ails-duplicate

Signed-off-by: Alex Ray <alray@nvidia.com>
Base automatically changed from astd-341-guardrails-creation-flow to main August 7, 2026 02:34
…uplicate

Signed-off-by: Alex Ray <alray@nvidia.com>
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Guardrails can now be duplicated from list and detail views. The modal preloads copied configuration data, derives a length-constrained -copy name, and submits the new guardrail. Shared copy-name logic also supports data designer jobs.

Changes

Guardrail duplication

Layer / File(s) Summary
Shared copy-name generation
web/packages/common/src/utils/entityName.ts, web/packages/common/src/utils/entityName.test.ts, web/packages/studio/src/components/NewDataDesignerJobForm/*
The shared utility generates valid, length-constrained copy names. Data designer jobs use the shared utility instead of a local suffix constant.
Duplicate modal behavior
web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.tsx, web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.test.tsx
The modal accepts sourceConfig, preloads copied values, updates its title, submits copied description and data, and validates duplicate-mode behavior.
List duplication wiring
web/packages/studio/src/components/dataViews/GuardrailsDataView/index.tsx, web/packages/studio/src/routes/guardrails/GuardrailsRoute/index.tsx
The data view adds a Duplicate action. The route opens the modal with the selected configuration.
Detail duplication action
web/packages/studio/src/routes/guardrails/GuardrailDetailRoute/GuardrailDetailActions.tsx
The detail view adds a Duplicate quick action and opens the modal with the current configuration.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant GuardrailsDataView
  participant GuardrailsRoute
  participant CreateGuardrailModal
  participant CreateMutation

  User->>GuardrailsDataView: Select Duplicate
  GuardrailsDataView->>GuardrailsRoute: Send selected GuardrailConfig
  GuardrailsRoute->>CreateGuardrailModal: Open with sourceConfig
  CreateGuardrailModal->>CreateGuardrailModal: Build copied name and preload fields
  User->>CreateGuardrailModal: Submit duplicate
  CreateGuardrailModal->>CreateMutation: Create copied guardrail
Loading

Suggested reviewers: a2bondar

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: adding duplicate guardrail creation in Studio.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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 astd-341-guardrails-duplicate

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.tsx (1)

94-103: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Use a complete GuardrailConfig fixture. SOURCE_CONFIG omits required response fields and uses as unknown as GuardrailConfig. Add the required fields instead. Both data schemas allow arbitrary object properties, so no production mapper or output-only-field assertion is needed.

🤖 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 `@web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.tsx`
around lines 94 - 103, Replace the incomplete SOURCE_CONFIG fixture in
CreateGuardrailModal/index.test.tsx (lines 20-25) with a complete
GuardrailConfig containing all required response fields, removing the unknown
cast. Keep the onSubmit payload mapping in CreateGuardrailModal/index.tsx (lines
94-103) unchanged; both data schemas already permit the fixture’s arbitrary
properties.

Source: Coding guidelines

🤖 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 `@web/packages/studio/src/components/dataViews/GuardrailsDataView/index.tsx`:
- Around line 24-28: Conditionally render the duplicate action in
GuardrailsDataView based on the optional onRequestDuplicate prop, so no
duplicate control appears when the handler is absent. Preserve the existing
action behavior when the handler is provided, and apply the same conditional
handling to the corresponding duplicate action instance noted in the comment.

---

Nitpick comments:
In `@web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.tsx`:
- Around line 94-103: Replace the incomplete SOURCE_CONFIG fixture in
CreateGuardrailModal/index.test.tsx (lines 20-25) with a complete
GuardrailConfig containing all required response fields, removing the unknown
cast. Keep the onSubmit payload mapping in CreateGuardrailModal/index.tsx (lines
94-103) unchanged; both data schemas already permit the fixture’s arbitrary
properties.
🪄 Autofix

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: Enterprise

Run ID: 0428dff5-a061-47cf-b443-26a4bcd27208

📥 Commits

Reviewing files that changed from the base of the PR and between 3fea04c and 2a34a8b.

📒 Files selected for processing (5)
  • web/packages/studio/src/components/dataViews/GuardrailsDataView/index.tsx
  • web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.test.tsx
  • web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.tsx
  • web/packages/studio/src/routes/guardrails/GuardrailDetailRoute/GuardrailDetailActions.tsx
  • web/packages/studio/src/routes/guardrails/GuardrailsRoute/index.tsx

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 31886/40497 78.7% 63.4%
Integration Tests 18514/38423 48.2% 20.8%

…uplicate

Signed-off-by: Alex Ray <alray@nvidia.com>
@aray12
aray12 enabled auto-merge August 7, 2026 22:03
Comment thread web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.tsx Outdated
Comment thread web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.test.tsx Outdated
Comment thread web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.test.tsx Outdated
Move the guardrail duplicate-name logic out of CreateGuardrailModal into
`toCopyName` in @nemo/common/src/utils/entityName, alongside the
ENTITY_NAME_MAX_LENGTH constant and name sanitizers it depends on.

Two fixes fall out of sharing it:

- Truncating at MAX - len('-copy') could land just after a hyphen and
  produce `my-guardrail--copy`, which ENTITY_NAME_REGEXP rejects for
  consecutive hyphens. Trailing hyphens are now stripped first.
- The Data Designer clone path had its own CLONE_NAME_SUFFIX and never
  truncated, so a 60-character job name cloned to 65 and failed
  validation. buildClonedJobRequest now uses the shared helper.

Also type the CreateGuardrailModal test fixture as a full GuardrailConfig
instead of casting through `unknown`, and use an NVIDIA NemoGuard model in
the example rails config.

Signed-off-by: Alex Ray <alray@nvidia.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 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 `@web/packages/common/src/utils/entityName.ts`:
- Around line 42-55: The toCopyName function can return the original name when a
maximum-length source already ends with the copy suffix. Ensure the generated
candidate always differs from name by shortening the base or applying another
deterministic valid fallback, while preserving length and naming constraints;
add a regression test in the entityName tests for 58 “a” characters followed by
“-copy”.
🪄 Autofix

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: Enterprise

Run ID: 3bfb72b1-6fd6-41f6-ad64-592660b6f132

📥 Commits

Reviewing files that changed from the base of the PR and between 2a34a8b and a7b496c.

📒 Files selected for processing (6)
  • web/packages/common/src/utils/entityName.test.ts
  • web/packages/common/src/utils/entityName.ts
  • web/packages/studio/src/components/NewDataDesignerJobForm/utils.test.ts
  • web/packages/studio/src/components/NewDataDesignerJobForm/utils.ts
  • web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.test.tsx
  • web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.test.tsx
  • web/packages/studio/src/routes/guardrails/CreateGuardrailModal/index.tsx

Comment thread web/packages/common/src/utils/entityName.ts
@aray12
aray12 added this pull request to the merge queue Aug 10, 2026
Merged via the queue into main with commit d9aa731 Aug 10, 2026
56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants