Skip to content

ENG-2194: Add custom default policy configuration support#7323

Merged
JadeCara merged 23 commits intomainfrom
ENG-2194-be-default-policy-configuration-api
Feb 12, 2026
Merged

ENG-2194: Add custom default policy configuration support#7323
JadeCara merged 23 commits intomainfrom
ENG-2194-be-default-policy-configuration-api

Conversation

@JadeCara
Copy link
Copy Markdown
Contributor

@JadeCara JadeCara commented Feb 5, 2026

Ticket

ENG-2194

Description Of Changes

Custom Default Policy Configuration

Add support for custom default policies per action type via ApplicationConfig. When no policy conditions match a privacy request, the PolicyEvaluator now:

  1. First checks for a custom default policy configured via the API (ApplicationConfig.api_set)
  2. Validates the custom default still exists and has rules for the action type
  3. Falls back to the system default if the custom default is missing or invalid

This enables administrators to override the system default policies (default_access_policy, default_erasure_policy, default_consent_policy) with organization-specific defaults.

Policy Conditions in API Responses

The policy list endpoint now eagerly loads and returns policy conditions in the response. PolicyResponse includes a new conditions field populated via a model validator that extracts the condition tree from the ORM relationship.

Location Groups & Regulations Support

Expanded location convenience field resolution to support location groups (e.g., "us", "ca" as groups, not just individual locations). The MUTUALLY_EXCLUSIVE_FIELDS set now includes location_groups and location_regulations for proper condition tiebreaking.

Code Changes

File Change
src/fides/api/task/conditional_dependencies/policy_evaluation.py Added _get_configured_default_policy_key() method and updated _get_default_policy() to check custom defaults first; added location_groups and location_regulations to MUTUALLY_EXCLUSIVE_FIELDS
src/fides/api/schemas/policy.py Added conditions field to PolicyResponse with extract_conditions model validator; modernized type hints (Listlist, Dictdict)
src/fides/api/api/v1/endpoints/policy_endpoints.py Added joinedload(Policy.conditions) to policy list query for eager loading
src/fides/api/task/conditional_dependencies/privacy_request/convenience_fields.py Added location_groups lookup before country code fallback in convenience field resolution
src/fides/api/util/default_policy_config.py New file with DEFAULT_POLICY_CONFIG_KEY constant shared between fides and fidesplus
tests/api/task/conditional_dependencies/test_policy_evaluation.py Added TestCustomDefaultPolicy test class (5 tests); expanded test_routes_by_location and test_ambiguous_tie_raises_error to parameterize over all location field types (location, country, groups, regulations)
tests/ops/api/v1/endpoints/privacy_request/test_privacy_request_endpoints.py Updated expected response assertions to include "conditions": {}
changelog/7323.yaml Added changelog entry

Steps to Confirm

Note: This PR provides the fides OSS infrastructure. End-to-end testing requires the companion fidesplus branch (ENG-2194-be-default-policy-configuration-api on fidesplus, PR #3050) which adds the API endpoints. Deploy both branches together to test.

Prerequisites: Create policies with conditions using the policy conditions endpoints from #3031.

  1. Verify policy conditions are returned in the policy list using GET /api/v1/dsr/policy
    Expected: Each policy includes a conditions field containing its condition tree ({} if no conditions).

  2. Set a custom default policy using PUT /api/v1/plus/dsr/policy/default
    { "action_type": "access", "policy_key": "my_custom_access_policy"}
    Expected: 200 response with updated config showing the custom policy key for access.

  3. Verify custom default is used when no conditions match using POST /api/v1/privacy-request
    [ { "identity": {"email": "test@example.com"}, "location": "XX", "action_type": "access" }]
    Expected: Request created using my_custom_access_policy (not default_access_policy).

  4. Reset to system default using PUT /api/v1/plus/dsr/policy/default
    { "action_type": "access", "policy_key": null}
    Expected: 200 response. Subsequent privacy requests with no matching conditions fall back to default_access_policy.

  5. Verify location group matching - Create a policy with a location_groups = eea condition, then POST /api/v1/privacy-request
    [ { "identity": {"email": "test@example.com"}, "location": "FR", "action_type": "access" }]
    Expected: France resolves to the eea group and matches the policy.

  6. Verify location regulation matching - Create a policy with a location_regulations = gdpr condition, then POST /api/v1/privacy-request
    [{"identity": {"email": "test@example.com"}, "location": "FR", "action_type": "access" }]
    Expected: France resolves to the gdpr regulation and matches the policy.

  7. Read the current default config using GET /api/v1/plus/dsr/policy/default
    Expected: Returns access, erasure, and consent fields (each null for system default or a policy key for custom).

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Add a db-migration This indicates that a change includes a database migration label to the entry if your change includes a DB migration
    • Add a high-risk This issue suggests changes that have a high-probability of breaking existing code label to the entry if your change includes a high-risk change (i.e. potential for performance impact or unexpected regression) that should be flagged
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • No UX review needed
  • Followup issues:
    • No followup issues
  • Database migrations:
    • No migrations
  • Documentation:

Made with Cursor

Allow configuring custom default policies per action type via
ApplicationConfig. Falls back to system defaults if custom
default is missing or invalid.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Feb 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fides-plus-nightly Ready Ready Preview, Comment Feb 12, 2026 7:28pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Feb 12, 2026 7:28pm

Request Review

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Feb 9, 2026

Deployment failed with the following error:

Creating the Deployment Timed Out.

@JadeCara JadeCara marked this pull request as ready for review February 9, 2026 21:30
@JadeCara JadeCara requested review from a team as code owners February 9, 2026 21:30
Jade Wibbels added 2 commits February 9, 2026 14:31
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR adds support for custom per-action default policies via ApplicationConfig.api_set, allowing PolicyEvaluator to prefer an administrator-configured default policy when no conditions match and to fall back to system-seeded defaults if the configured key is missing/invalid.

It also extends location convenience-field resolution to support location groups/regulations, updates specificity/tiebreaking to treat those fields as mutually exclusive with other location selectors, and updates the policy list endpoint to eager-load rules (including storage_destination) and conditions so policy responses can include a new conditions field derived from the Policy.conditions relationship.

Main issue to address before merge: the new PolicyResponse.conditions validator currently only handles dict and plain list inputs; if SQLAlchemy provides a non-list collection type, the API will silently return {} even when conditions exist, which breaks the intended API contract for GET /api/v1/policy.

Confidence Score: 4/5

  • Mostly safe to merge, but there is a correctness risk in how policy conditions are serialized to the API response.
  • Core behavior changes (custom default selection, location tiering, eager loading) are covered by tests and use defensive config parsing. The remaining concern is PolicyResponse.extract_conditions() relying on isinstance(v, list); if the ORM relationship is not a plain list type, conditions may incorrectly serialize as {} despite DB state, undermining the new API feature.
  • src/fides/api/schemas/policy.py

Important Files Changed

Filename Overview
changelog/7323.yaml Adds changelog entry for custom default policy configuration support.
src/fides/api/api/v1/endpoints/policy_endpoints.py Eager-loads policy rules/storage destinations and policy conditions for the list endpoint to avoid N+1 queries.
src/fides/api/schemas/policy.py Adds conditions field with a validator extracting condition trees; potential bug if ORM relationship isn't a plain list type, leading to {} even when conditions exist.
src/fides/api/task/conditional_dependencies/policy_evaluation.py Adds ApplicationConfig-based custom default policy lookup with defensive type checks; expands mutually exclusive location fields and tiering.
src/fides/api/task/conditional_dependencies/privacy_request/convenience_fields.py Extends location convenience resolution to support location groups and group fallback when extracting country codes.
src/fides/api/util/default_policy_config.py Introduces shared DEFAULT_POLICY_CONFIG_KEY constant for ApplicationConfig api_set default policies.
tests/api/task/conditional_dependencies/test_policy_evaluation.py Adds coverage for custom default policies and parameterizes location-based routing/tie-breaking across location/country/groups/regulations.
tests/ops/api/v1/endpoints/privacy_request/test_privacy_request_endpoints.py Updates privacy request endpoint expectations to include empty policy conditions field.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

7 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@JadeCara
Copy link
Copy Markdown
Contributor Author

JadeCara commented Feb 9, 2026

@greptile please review

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@JadeCara
Copy link
Copy Markdown
Contributor Author

JadeCara commented Feb 9, 2026

@greptile please review

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Jade Wibbels added 2 commits February 9, 2026 16:13
@JadeCara
Copy link
Copy Markdown
Contributor Author

JadeCara commented Feb 9, 2026

@greptile please review

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@JadeCara
Copy link
Copy Markdown
Contributor Author

@greptile please review

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@JadeCara
Copy link
Copy Markdown
Contributor Author

@greptile please review

@JadeCara JadeCara requested a review from johnewart February 10, 2026 00:37
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@JadeCara
Copy link
Copy Markdown
Contributor Author

@greptile please review and take comments into account

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link
Copy Markdown
Collaborator

@johnewart johnewart left a comment

Choose a reason for hiding this comment

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

Looks good - the questions I had we talked about out-of-band 👍

@JadeCara JadeCara added this pull request to the merge queue Feb 12, 2026
Merged via the queue into main with commit 7d9a0cc Feb 12, 2026
54 checks passed
@JadeCara JadeCara deleted the ENG-2194-be-default-policy-configuration-api branch February 12, 2026 23:06
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