fix: preserve duplicate-named policies for LLM providers and proxies#2868
Open
renuka-fernando wants to merge 3 commits into
Open
fix: preserve duplicate-named policies for LLM providers and proxies#2868renuka-fernando wants to merge 3 commits into
renuka-fernando wants to merge 3 commits into
Conversation
Two policies with the same name (e.g. two set-headers guardrails) attached at the API/global level were collapsed to a single instance, so only the latest reached the gateway. Two independent root causes: - gateway-controller: collectAPIPolicies used a map keyed by policy name, overwriting earlier entries. Return an ordered slice instead and simplify buildPolicyChain to prepend it. Fixes all kinds (RestApi, WebSubApi, Mcp, LlmProvider, LlmProxy) at once. - platform-api: the globalPolicies carry-through loop checked hasGlobalPolicy against the accumulator it was appending to, dropping the second user duplicate before it reached the WebSocket. Snapshot the system-generated policy names first and skip only against those, in both the provider and proxy deployment paths. Operation-level policies were unaffected in both services. Adds regression tests covering the duplicate API/global-level case.
The provider and proxy guardrails tabs deduplicated globalPolicies by name+version before sending, updating the existing entry instead of adding a new one — so a second same-named guardrail (e.g. two set-headers) could never be attached. This mirrored the backend drop now fixed in gateway-controller and platform-api. - Always push new global-scope guardrails instead of merging by name+version - Always append the new path to a resource-scope policy instead of skipping when the path already exists - Add a /proxy dev route to the vite proxy config
The new-provider guardrails section deduplicated staged guardrails by name, replacing the existing entry, so a second same-named guardrail (e.g. two set-headers) could never be attached. It was also React-keyed by name, so duplicates collided and remove-by-name deleted every copy. - Add a unique id to each staged GuardrailSelection - Always append a new guardrail instead of merging by name - Key the pill list by id and remove by id, clearing the drawer selection only when no duplicate of that name remains Signed-off-by: Renuka Fernando <renukapiyumal@gmail.com>
renuka-fernando
requested review from
AnuGayan,
Arshardh,
CrowleyRajapakse,
HeshanSudarshana,
HiranyaKavishani,
Induwara04,
Krishanx92,
PasanT9,
Piumal1999,
RakhithaRR,
Tharsanan1,
Thushani-Jayasekera,
VirajSalaka,
ashera96,
chamilaadhi,
dushaniw,
hisanhunais,
lasanthaS,
malinthaprasan,
pubudu538,
senthuran16,
tgtshanika,
tharikaGitHub,
tharindu1st and
thivindu
as code owners
July 25, 2026 10:49
Contributor
📝 WalkthroughWalkthroughThe changes preserve duplicate guardrail policies across workspace state, deployment YAML, and gateway policy chains. Guardrail removal now uses unique staged-entry IDs. The AI workspace also updates its development image tag and adds a BFF proxy route. ChangesDuplicate policy preservation
AI workspace development updates
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant GuardrailsUI
participant PlatformAPI
participant GatewayTransformer
GuardrailsUI->>PlatformAPI: submit repeated guardrail policies
PlatformAPI->>PlatformAPI: preserve duplicate user policies in deployment YAML
PlatformAPI->>GatewayTransformer: provide ordered policy configuration
GatewayTransformer-->>GuardrailsUI: produce policy chains with duplicate instances
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Fix #2823
Fix #2850
Attaching two policies with the same name (e.g. two
set-headersguardrails) at the API/global level for an LLM provider or proxy silently collapsed them to a single instance, so only the last one reached the gateway. The problem existed across the whole stack — the gateway-controller, platform-api, and the AI workspace portal each independently deduplicated by policy name — and was reproducible both when editing an existing provider/proxy and when creating a new provider.Goals
Allow the same policy to be attached more than once at the API/global scope, so every duplicate-named policy is preserved end-to-end from the UI through platform-api and the gateway-controller to the gateway.
Approach
collectAPIPoliciesused a map keyed by policy name, overwriting earlier entries. Return an ordered slice instead and simplifybuildPolicyChainto prepend it. Fixes all kinds (RestApi, WebSubApi, Mcp, LlmProvider, LlmProxy) at once.globalPoliciescarry-through loop checkedhasGlobalPolicyagainst the accumulator it was appending to, dropping the second user duplicate before it reached the WebSocket. Snapshot the system-generated policy names first and skip only against those, in both the provider and proxy deployment paths.globalPoliciesby name+version before sending. Always push new global-scope guardrails, and always append the new path to a resource-scope policy instead of skipping when it already exists.idto each staged guardrail, always append, and key/remove byid— clearing the drawer selection only when no duplicate of that name remains.Operation-level policies were unaffected in every case.
User stories
As an API platform user, I can attach the same policy (e.g. two
set-headersguardrails) more than once to an LLM provider or proxy at the API/global level, and all instances take effect at the gateway.Documentation
N/A — bug fix restoring intended behaviour; no user-facing API or doc change.
Automation tests
Security checks
Samples
N/A
Related PRs
N/A
Test environment
Go workspace (gateway-controller, platform-api); AI workspace portal via Vite dev server, Chrome.
Checklist