Skip to content

Reject unknown policyType filter values in the Policy API - #5310

Open
SEPURI-SAI-KRISHNA wants to merge 2 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:policy-type-filter-validation
Open

Reject unknown policyType filter values in the Policy API#5310
SEPURI-SAI-KRISHNA wants to merge 2 commits into
apache:mainfrom
SEPURI-SAI-KRISHNA:policy-type-filter-validation

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown

The Policy API resolves the optional policyType query parameter with
PolicyType.fromName(...), which returns null for any name it does not
recognize. null is also the sentinel that means "no filter", so an
unrecognized value silently degrades into an unfiltered listing:

  • GET /polaris/v1/{prefix}/namespaces/{namespace}/policies?policyType=...
  • GET /polaris/v1/{prefix}/applicable-policies?policyType=...

A misspelled type such as system.data_compaction (underscore instead of
hyphen) therefore returns HTTP 200 together with policies of every type,
and the client has no way to tell a filtered result from an unfiltered one.
For getApplicablePolicies this is the more damaging case: a caller asking
which snapshot-expiry policy applies to a table receives policies of all
types and may act on the wrong one.

createPolicy already rejects unknown type names with a BadRequestException
(PolicyCatalog#createPolicy), so the two listing endpoints were also
inconsistent with the rest of the same API, and with their own specification,
which documents a 400 response.

Changes

PolicyCatalogUtils#resolvePolicyTypeFilter now resolves the raw query
parameter, and both call sites in PolicyCatalogAdapter use it:

  • an absent (null) or empty value still means "no filter" — the parameter is
    declared allowEmptyValue: true in spec/polaris-catalog-apis/policy-apis.yaml,
    so empty must keep working;
  • any other value must name a known policy type; an unknown name is rejected
    with BadRequestException, which maps to HTTP 400.

No public interface or extension point is changed: PolicyCatalogUtils is an
internal helper in the service module, and PolicyType is untouched.

Testing

  • PolicyCatalogUtilsTest (new): parameterized over every PredefinedPolicyTypes
    value for the accepted cases, plus null / empty for "no filter", plus unknown
    names, wrong separators, wrong case and surrounding whitespace for the rejected
    cases.
  • PolarisPolicyServiceIntegrationTest: two new end-to-end tests assert HTTP 400
    from listPolicies and getApplicablePolicies when an unknown policyType is
    supplied while a real policy exists in the namespace.

Both integration tests were confirmed to fail against the unpatched resolver
(expected: 400 but was: 200) and to pass with the fix. PolicyServiceIntegrationTest
runs 48 tests with 0 failures, and spotlessCheck / checkstyleMain /
checkstyleTest pass for :polaris-runtime-service and :polaris-tests.

Notes

While reading this area I noticed that listPolicies accepts pageToken and
pageSize and declares next-page-token in its response schema, but the
implementation ignores all three and always lists everything. That is a
separate change with design questions of its own (result ordering, the
Set<PolicyIdentifier> response shape), so it is deliberately not bundled here;
I plan to raise it as its own issue.

AI assistance was used while preparing this change. I have reviewed the
implementation and the tests, and I am responsible for the contribution.

Checklist

  • 🛡️ Don't disclose security issues! (contact security@apache.org)
  • 🔗 Clearly explained why the changes are needed, or linked related issues
  • 🧪 Added/updated tests with good coverage, or manually tested (and explained how)
  • 💡 Added comments for complex logic
  • 🧾 Updated CHANGELOG.md (if needed)
  • 📚 Updated documentation in site/content/in-dev/unreleased (if needed) — no user-facing
    documentation covers the policyType parameter, so no update was required

@github-project-automation github-project-automation Bot moved this to PRs In Progress in Basic Kanban Board Aug 17, 2026
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNA marked this pull request as ready for review August 17, 2026 09:46
Copilot AI lite review requested due to automatic review settings August 17, 2026 09:46

Copilot AI 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.

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Updates the Policy API to reject unknown policyType query parameter values (HTTP 400) instead of silently treating them as “no filter,” preventing accidental unfiltered listings and incorrect applicable-policy selection.

Changes:

  • Added PolicyCatalogUtils.resolvePolicyTypeFilter(...) to centrally resolve/validate the policyType query parameter (null/empty allowed; unknown rejected).
  • Updated PolicyCatalogAdapter listing endpoints to use the new resolver.
  • Added unit + integration tests to verify HTTP 400 behavior and updated CHANGELOG.md.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogUtils.java Adds shared resolver that enforces valid policyType values and throws BadRequestException for unknown types.
runtime/service/src/main/java/org/apache/polaris/service/catalog/policy/PolicyCatalogAdapter.java Switches policy listing endpoints to use the centralized resolver (enabling 400 on unknown type).
runtime/service/src/test/java/org/apache/polaris/service/catalog/policy/PolicyCatalogUtilsTest.java Adds focused unit tests for accepted vs rejected policyType inputs.
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisPolicyServiceIntegrationTest.java Adds end-to-end coverage to ensure unknown policyType yields HTTP 400.
CHANGELOG.md Documents the behavior change for API consumers.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

The listPolicies and getApplicablePolicies endpoints resolved the optional
policyType query parameter with PolicyType.fromName, which returns null for
any unrecognized name. Since null is also the sentinel meaning "no filter",
an unrecognized value silently degraded into an unfiltered listing: a
misspelled type such as system.data_compaction returned HTTP 200 along with
policies of every type, leaving the client unable to distinguish a filtered
result from an unfiltered one.

The raw parameter is now resolved by PolicyCatalogUtils.resolvePolicyTypeFilter.
An absent or empty value continues to mean "no filter", as the parameter is
declared with allowEmptyValue: true; any other value must name a known policy
type and is otherwise rejected with HTTP 400. This matches the behavior of
createPolicy, which already rejected unknown type names, and the 400 response
documented for both endpoints.
The rejection message named only the offending value, leaving a client to
consult the specification or the source to discover what it should have sent.
It now quotes the supplied value and lists the accepted names, derived from
PredefinedPolicyTypes so the message and the set actually accepted by
PolicyType.fromName cannot drift apart. A test asserts every valid type name
appears in the message.
@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNA force-pushed the policy-type-filter-validation branch from 36155d1 to 4a12083 Compare August 18, 2026 02:55
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.

2 participants