Skip to content

Validate policy params for LLM operationPolicies and the policies list - #3383

Merged
renuka-fernando merged 2 commits into
wso2:mainfrom
thivindu:bug-fixes
Sep 18, 2026
Merged

renuka-fernando merged 2 commits into
wso2:mainfrom
thivindu:bug-fixes

Conversation

@thivindu

@thivindu thivindu commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Purpose

PolicyValidator validates policy params against the policy definition's declared JSON Schema for most artifact types, but silently skips it for two of the five policy collections an LlmProvider/LlmProxy can declare. validateLLMPolicyRefs resolved the policy reference for the operation-level and deprecated lists and then discarded the resolved definition:

// Operation-level policies: validate name + version existence.
_, errs := pv.validatePolicyRef(policy.Name, policy.Version, ...)   // ← the *models.PolicyDefinition is dropped

Only the global (api-level) list routed through validatePolicy, which performs the schema check.

Coverage before this PR:

Artifact kind Policy collection Name + version Params vs. schema
RestApi spec.policies, spec.operations[].policies
Mcp spec.policies
LlmProvider / LlmProxy spec.globalPolicies
LlmProvider / LlmProxy spec.operationPolicies[].paths[].params
LlmProvider / LlmProxy spec.policies[].paths[].params (deprecated)

A misconfigured operation-level LLM policy therefore deployed successfully instead of being rejected: missing required params, out-of-range values and unknown properties all passed. The failure surfaced later at runtime, where the policy is dropped or misbehaves with no deploy-time signal — and the same params on the same policy were correctly rejected when attached as a globalPolicy, which made the behavior look arbitrary.

Resolves:

Goals

Schema-validate params for the two remaining LLM policy collections, so an invalid operation-level policy fails at deploy time with a field path naming the offending param — matching what RestApi, Mcp and LLM globalPolicies already do.

Approach

validateLLMPolicyRefs now uses the *models.PolicyDefinition that validatePolicyRef was already returning, and validates each path attachment's params:

policyDef, errs := pv.validatePolicyRef(policy.Name, policy.Version, fieldPath)
if len(errs) > 0 { errors = append(errors, errs...); continue }
for j := range policy.Paths {
    errors = append(errors, pv.validateAttachedPolicyParams(policyDef, policy.Paths[j].Params,
        fmt.Sprintf("%s.paths[%d]", fieldPath, j))...)
}

A new validateAttachedPolicyParams helper coerces then schema-checks one params map. It handles the two things that differ from the api-level path:

  • A nil params map is still validated, not skipped — otherwise omitting params: entirely would bypass a schema's required list.
  • Coercion runs first, since template rendering always yields strings ({{ env "LIMIT" }}"100" for an integer param), mirroring validatePolicy's handling of api-level params. Both call sites validate rendered config (RenderSpec at llm_deployment.go:270/:457, validation at :312/:498), so this is the correct order.

An unresolvable name/version reports once and skips param validation, rather than repeating the same error per path.

User stories

As an API platform user deploying an LlmProvider/LlmProxy, when I attach an operation-level policy with invalid params, the deploy is rejected with an error naming the param — instead of succeeding and silently misbehaving at runtime.

Automation tests

  • Unit tests — 8 new tests in policy_validator_llm_test.go (+188 lines), covering: valid params; missing required / out-of-range / unknown-property; absent params map; string→int coercion; a definition with no parameter schema; unresolvable ref not re-reporting per path; the deprecated policies list; and the template-merge rationale. Full gateway-controller module passes (go build ./..., go vet, go test ./...).
  • Integration tests — none added. The change is confined to a pure validation function with no I/O; the behavior is fully covered at unit level.

Regression check against real policy definitions

Because this turns previously-accepted config into rejected config, verified it doesn't reject anything valid: loaded all 36 real policy definitions from wso2/gateway-controllers and validated every operation-level/deprecated params block in gateway/examples/*.yaml (api-key-auth, content-length-guardrail, llm-header-router, llm-cost-based-ratelimit, openai-to-bedrock-transformer, …) — all clean, no false positives.

Behavior change to be aware of: an LlmProvider/LlmProxy already deployed with invalid operation-level policy params will now fail validation on its next deploy/update. That is the intended fix, but it can surface as a new failure on config that previously "worked".

Test environment

Go 1.26.2, macOS (darwin 24.6.0). Validation logic is platform- and DB-independent; no browser or database involvement.

@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Warning

Review limit reached

Next included review available in 5 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: e03f356c-da91-4008-9cf4-30d233839d66

📥 Commits

Reviewing files that changed from the base of the PR and between 25c42b0 and 9379646.

📒 Files selected for processing (2)
  • tests/framework/suites/it/features/token_based_ratelimit.feature
  • tests/framework/suites/it/features/token_based_ratelimit_provider_templates.feature

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 71793db5-dcab-4efa-acd3-efaa89eb9b36

📥 Commits

Reviewing files that changed from the base of the PR and between 765600d and 25c42b0.

📒 Files selected for processing (2)
  • gateway/gateway-controller/pkg/config/policy_validator.go
  • gateway/it/features/token-based-ratelimit.feature
💤 Files with no reviewable changes (1)
  • gateway/it/features/token-based-ratelimit.feature

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

LLM operation-level and deprecated policy attachments now validate per-path parameters against resolved policy schemas. Validation coerces rendered values, checks absent parameter maps, and reports schema errors. Tests cover the validation cases, and token-based rate-limit scenarios now use policy defaults.

Changes

LLM policy parameter validation

Layer / File(s) Summary
Validate attached policy parameters
gateway/gateway-controller/pkg/config/policy_validator.go
Resolved operation-level and deprecated policy references now validate each path’s parameters. Validation coerces schema-defined values and treats missing maps as empty objects.
Test policy parameter validation and policy defaults
gateway/gateway-controller/pkg/config/policy_validator_llm_test.go, gateway/it/features/token-based-ratelimit.feature
Tests cover required and unknown parameters, coercion, absent maps, schema-less definitions, unresolved references, deprecated policies, and template-extraction parameters. Token-based rate-limit scenarios remove explicit algorithm and backend settings.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Low

Merge Risk: ⚪ Minimal · up to 25c42

The updated validation and integration scenarios retain their intended behavior, with no concrete merge-blocking risk identified.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR removes explicit algorithm: fixed-window and backend: memory settings from many scenarios in gateway/it/features/token-based-ratelimit.feature. These changes do not validate LLM policy pa… Restore the removed algorithm and backend settings, or move this defaults-related change to a separate pull request with its own requirement and justification.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the primary change: validating policy parameters for LLM operation policies and the policies list.
Description check ✅ Passed The description is detailed and covers the purpose, goals, approach, user story, automation tests, and test environment. It omits the Documentation, Security checks, Samples, and Related PRs sections,…
Linked Issues check ✅ Passed Issue #3381 requires schema validation for operationPolicies[].paths[].params and deprecated policies[].paths[].params on LLM providers and proxies. The shared validateLLMPolicyRefs implementati…
Full details: Out of Scope Changes check

Explanation

The PR removes explicit algorithm: fixed-window and backend: memory settings from many scenarios in gateway/it/features/token-based-ratelimit.feature. These changes do not validate LLM policy parameters and are not connected to issue #3381. They change integration-test configuration independently of the requested validation fix.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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

coderabbitai[bot]
coderabbitai Bot previously approved these changes Sep 7, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Dependency Validation Results

Dependency name: github.com/klauspost/compress
Version: v1.19.2
Approved: ❌ No - Module not found in dependency registry

Dependency name: github.com/a2aproject/a2a-go/v2
Version: v2.5.0
Allowed range: >=v2.5.0
Approved: ✅ Yes

Dependency name: github.com/pb33f/libopenapi
Version: v0.38.7
Allowed range: >=v0.28.2
Approved: ✅ Yes

Dependency name: github.com/pb33f/libopenapi-validator
Version: v0.14.0
Allowed range: >=v0.14.0
Approved: ✅ Yes

Dependency name: github.com/go-playground/validator/v10
Version: v10.30.4 (was v10.30.1)
Allowed range: >=v10.30.1
Approved: ✅ Yes

Dependency name: github.com/gorilla/websocket
Version: v1.5.3 (was v1.5.4-0.20250319132907-e064f32e3674)
Allowed range: >=v1.5.3
Approved: ✅ Yes

Dependency name: github.com/jackc/pgx/v5
Version: v5.11.0 (was v5.9.2)
Allowed range: >=v5.8.0
Approved: ✅ Yes

Dependency name: github.com/knadh/koanf/parsers/toml/v2
Version: v2.2.2 (was v2.2.0)
Allowed range: >=v2.2.0
Approved: ✅ Yes

Dependency name: github.com/knadh/koanf/providers/confmap
Version: v1.0.1 (was v1.0.0)
Allowed range: >=v1.0.0
Approved: ✅ Yes

Dependency name: github.com/knadh/koanf/v2
Version: v2.3.6 (was v2.3.2)
Allowed range: >=v2.3.2
Approved: ✅ Yes

Dependency name: github.com/mattn/go-sqlite3
Version: v1.14.52 (was v1.14.41)
Allowed range: >=v1.14.32
Approved: ✅ Yes

Dependency name: github.com/microsoft/go-mssqldb
Version: v1.11.0 (was v1.10.0)
Allowed range: >=v1.10.0
Approved: ✅ Yes

Dependency name: github.com/oapi-codegen/runtime
Version: v1.7.0 (was v1.5.0)
Allowed range: >=v1.2.0
Approved: ✅ Yes

Dependency name: github.com/stretchr/testify
Version: v1.12.1 (was v1.11.1)
Allowed range: >=v1.11.1
Approved: ✅ Yes

Dependency name: golang.org/x/crypto
Version: v0.57.0 (was v0.54.0)
Allowed range: >=v0.31.0
Approved: ✅ Yes

Dependency name: github.com/cucumber/godog
Version: v0.16.0
Allowed range: >=v0.15.0
Approved: ✅ Yes

Dependency name: github.com/golang-jwt/jwt/v5
Version: v5.3.1
Allowed range: >=v5.3.1
Approved: ✅ Yes

Dependency name: github.com/jackc/pgx/v5
Version: v5.11.0
Allowed range: >=v5.8.0
Approved: ✅ Yes

Dependency name: github.com/knadh/koanf/parsers/toml/v2
Version: v2.2.2
Allowed range: >=v2.2.0
Approved: ✅ Yes

Dependency name: github.com/mattn/go-sqlite3
Version: v1.14.52
Allowed range: >=v1.14.32
Approved: ✅ Yes

Dependency name: github.com/microsoft/go-mssqldb
Version: v1.11.0
Allowed range: >=v1.10.0
Approved: ✅ Yes

Dependency name: github.com/moby/moby/api
Version: v1.56.0
Allowed range: >=v1.56.0
Approved: ✅ Yes

Dependency name: github.com/moby/moby/client
Version: v0.6.0
Allowed range: >=v0.6.0
Approved: ✅ Yes

Dependency name: github.com/modelcontextprotocol/go-sdk
Version: v1.7.0
Allowed range: >=v1.2.0
Approved: ✅ Yes

Dependency name: github.com/mxschmitt/playwright-go
Version: v0.6201.1
Allowed range: >=v0.6201.1
Approved: ✅ Yes

Dependency name: github.com/stretchr/testify
Version: v1.12.1
Allowed range: >=v1.11.1
Approved: ✅ Yes

Dependency name: github.com/testcontainers/testcontainers-go
Version: v0.44.0
Allowed range: >=v0.40.0
Approved: ✅ Yes

Dependency name: github.com/testcontainers/testcontainers-go/modules/compose
Version: v0.44.0
Allowed range: >=v0.43.0
Approved: ✅ Yes

Dependency name: golang.org/x/crypto
Version: v0.56.0
Allowed range: >=v0.31.0
Approved: ✅ Yes

Dependency name: gopkg.in/yaml.v3
Version: v3.0.1
Allowed range: >=v3.0.1
Approved: ✅ Yes


Next Steps

  1. Review the validation failures listed above
  2. Check if dependencies are in the approved dependency list
  3. Options to resolve:
    • Remove the unapproved dependencies from this PR
    • OR submit a PR to add these dependencies to the approved list in engineering-governance
  4. Once resolved, push changes to re-run validation

This PR is blocked until all dependencies are approved.

⚠️ Please verify the scope of the dependencies usage is necessary

coderabbitai[bot]
coderabbitai Bot previously approved these changes Sep 18, 2026
@codecov-commenter

codecov-commenter commented Sep 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 51.80%. Comparing base (51bb7a7) to head (9379646).
⚠️ Report is 29 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3383      +/-   ##
==========================================
- Coverage   51.81%   51.80%   -0.01%     
==========================================
  Files         955      957       +2     
  Lines      136747   137561     +814     
  Branches     4447     4447              
==========================================
+ Hits        70849    71270     +421     
- Misses      59004    59389     +385     
- Partials     6894     6902       +8     
Flag Coverage Δ
ai-workspace-bff-integration 39.58% <ø> (ø)
ai-workspace-bff-unit 75.00% <ø> (ø)
ai-workspace-ui-integration 25.94% <ø> (+0.08%) ⬆️
api-portal-server-integration 58.10% <ø> (ø)
api-portal-ui-integration 31.11% <ø> (+0.01%) ⬆️
gateway-controller-integration 44.65% <66.66%> (+0.02%) ⬆️
gateway-controller-unit 52.14% <100.00%> (+0.04%) ⬆️
platform-api-integration 41.27% <ø> (-0.73%) ⬇️
platform-api-unit 29.30% <ø> (-0.45%) ⬇️
policy-engine-integration 36.58% <ø> (-0.46%) ⬇️
policy-engine-unit 59.31% <ø> (+1.70%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@thivindu

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@renuka-fernando
renuka-fernando merged commit 1f34293 into wso2:main Sep 18, 2026
17 of 31 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.

3 participants