Skip to content

ENG-2539: Allow extra fields in JiraTicketSchema secrets#7605

Merged
JadeCara merged 8 commits intomainfrom
ENG-2539/jira-secrets-extra-allow
Mar 16, 2026
Merged

ENG-2539: Allow extra fields in JiraTicketSchema secrets#7605
JadeCara merged 8 commits intomainfrom
ENG-2539/jira-secrets-extra-allow

Conversation

@JadeCara
Copy link
Copy Markdown
Contributor

@JadeCara JadeCara commented Mar 9, 2026

Ticket ENG-2539

Description Of Changes

Allow extra fields in JiraTicketSchema so that Fidesplus can store additional configuration (project key, issue type, templates, etc.) in the same secrets dict without requiring schema changes in the OSS repo.

Sets model_config = ConfigDict(extra="allow") on JiraTicketSchema only — the base FidesSchema behavior is unchanged.

Code Changes

  • src/fides/api/schemas/connection_configuration/connection_secrets_jira_ticket.py - Add model_config = ConfigDict(extra="allow") and update docstring
  • tests/service/test_jira_ticket_connection.py - Update test to verify extra fields are preserved (was testing they were ignored)

Steps to Confirm

  1. Instantiate JiraTicketSchema with extra fields:
    from fides.api.schemas.connection_configuration import JiraTicketSchema
    schema = JiraTicketSchema(access_token="tok", project_key="PLAY", summary_template="DSR: {{ request_type }}")
    assert schema.project_key == "PLAY"
    assert schema.summary_template == "DSR: {{ request_type }}"
  2. Verify standard fields still work as before (empty schema, partial, full)
  3. Verify other connection secret schemas are unaffected (extra fields still forbidden on base FidesSchema)

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:
    • All UX related changes have been reviewed by a designer
    • No UX review needed
  • Followup issues:
    • Followup issues created
    • No followup issues
  • Database migrations:
    • Ensure that your downrev is up to date with the latest revision on main
    • Ensure that your downgrade() migration is correct and works
      • If a downgrade migration is not possible for this change, please call this out in the PR description!
    • No migrations
  • Documentation:
    • Documentation complete, PR opened in fidesdocs
    • Documentation issue created in fidesdocs
    • If there are any new client scopes created as part of the pull request, remember to update public-facing documentation that references our scope registry
    • No documentation updates required

Summary by CodeRabbit

Release Notes

  • Changed
    • Jira ticket schemas now preserve additional metadata fields such as project key, issue type, and templates instead of discarding them.

The Pydantic schema for jira_ticket secrets was stripping extra fields
during validation. This meant PATCH /secret couldn't merge template
config (project_key, issue_type, templates) alongside OAuth tokens.

Setting extra="allow" lets Fidesplus store arbitrary config in the
same secrets dict without requiring fides schema changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 9, 2026

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

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
fides-plus-nightly Ignored Ignored Preview Mar 10, 2026 4:35pm
fides-privacy-center Ignored Ignored Mar 10, 2026 4:35pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 39a4c66b-fd16-4e62-a00d-13153974bdcf

📥 Commits

Reviewing files that changed from the base of the PR and between 75a2a4f and 6d30721.

📒 Files selected for processing (1)
  • changelog/7605-jira-ticket-extra-fields.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • changelog/7605-jira-ticket-extra-fields.yaml

📝 Walkthrough

Walkthrough

This change enables JiraTicketSchema to store additional fields (project_key, issue_type, templates) by allowing extra attributes in the schema, and updates the masking utility to preserve these extra fields when the schema permits additional properties. Tests validate the new behavior.

Changes

Cohort / File(s) Summary
Changelog
changelog/7605-jira-ticket-extra-fields.yaml
New changelog entry documenting the change to allow extra fields in JiraTicketSchema for preserving Jira ticket metadata.
Schema Configuration
src/fides/api/schemas/connection_configuration/connection_secrets_jira_ticket.py
Added ConfigDict(extra="allow") to JiraTicketSchema to permit storage of additional fields beyond defined OAuth token fields; updated docstring to reflect support for extra metadata fields.
Masking Utility
src/fides/api/util/masking_util.py
Enhanced logic to check additionalProperties in secret schema and preserve non-schema fields when permitted; existing masking behavior for defined fields remains unchanged.
Test Coverage
tests/ops/schemas/connection_configuration/test_connection_config.py, tests/service/test_jira_ticket_connection.py
Added test validating mask behavior with additional properties allowed; renamed and updated existing test to verify extra fields are preserved rather than ignored.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Extra fields now flourish, no longer dismissed,
Jira's rich metadata no longer get missed,
Schema stays flexible, masking stays true,
Preserving what matters—both old knowledge and new! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: allowing extra fields in JiraTicketSchema for storing additional Jira secrets without schema modifications.
Description check ✅ Passed The description follows the template structure with ticket reference, detailed explanation of changes, specific code file changes, clear steps to confirm, and completed pre-merge checklist items.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ENG-2539/jira-secrets-extra-allow

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

Jade Wibbels and others added 5 commits March 9, 2026 17:58
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
set_secrets was assigning a Pydantic model object to the secrets
column, which SQLAlchemy's MutableDict rejects. Call model_dump()
to convert to a plain dict first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mask_sensitive_fields was dropping any secret keys not in the schema
properties. For schemas with extra="allow" (like JiraTicketSchema),
this silently stripped saved data from the GET response even though
it was persisted in the DB.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only preserve fields not in the schema when additionalProperties is true
(i.e. the Pydantic model uses extra="allow"). This fixes test failures
where non-schema fields like url=None were leaking into responses for
standard connection types like Postgres.

Schemas like JiraTicketSchema that use extra="allow" will have their
additional fields preserved in API responses, while all other connection
types maintain the existing behavior of dropping unknown fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JadeCara JadeCara marked this pull request as ready for review March 10, 2026 16:02
@JadeCara JadeCara requested a review from a team as a code owner March 10, 2026 16:02
@JadeCara JadeCara requested review from galvana and removed request for a team March 10, 2026 16:02
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@src/fides/api/util/masking_util.py`:
- Around line 40-43: The current branch in masking_util.py that assigns extra
fields when allows_additional is True (new_connection_secrets[key] = value) can
leak sensitive extension data; change it to apply the same masking logic used
for schema fields instead of blindly preserving value — detect sensitive extra
keys (e.g., key.lower().endswith("_secret") or key.lower().endswith("_token"))
and replace them with the masked placeholder, otherwise include the original or
sanitized value; reuse the existing masking helper/function used elsewhere in
this module to ensure consistent behavior for keys handled by allows_additional,
and add a small unit test that verifies keys like "api_secret" and
"access_token" are masked while non-sensitive extras are preserved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d2997f51-c800-4189-a5d5-c1ed39147899

📥 Commits

Reviewing files that changed from the base of the PR and between 9d24a80 and 75a2a4f.

📒 Files selected for processing (6)
  • changelog/7605-jira-ticket-extra-fields.yaml
  • src/fides/api/models/messaging.py
  • src/fides/api/schemas/connection_configuration/connection_secrets_jira_ticket.py
  • src/fides/api/util/masking_util.py
  • tests/ops/schemas/connection_configuration/test_connection_config.py
  • tests/service/test_jira_ticket_connection.py

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 10, 2026

Greptile Summary

This PR allows JiraTicketSchema to accept and preserve extra fields (e.g. project_key, issue_type, templates) by setting model_config = ConfigDict(extra="allow"), enabling Fidesplus to store additional Jira configuration alongside core OAuth secrets without requiring schema changes in the OSS repo. The schema change itself is minimal and well-scoped. However, there are two notable concerns:

  • masking_util.py — potential silent failure: The new elif allows_additional: branch in mask_sensitive_fields checks the truthiness of additionalProperties. Pydantic v2 (v2.12.4 is in use) generates "additionalProperties": {} (empty dict) for extra="allow" schemas, which is falsy in Python. The unit test for this branch uses a hand-crafted fixture with boolean True, so it passes — but when the actual JiraTicketSchema.model_json_schema() output is used (via get_connection_type_secret_schema), extra fields may be silently dropped in masked API responses. A lightweight integration test exercising the real schema-generation-to-masking pipeline would confirm the two halves of the fix actually compose correctly.
  • messaging.py — undocumented, unrelated change: The serialization change in MessagingConfig.set_secrets (calling model_dump() before storing) appears correct in principle but is completely absent from the PR description and is not related to the Jira schema work. The inconsistency between model_dump() here and model_dump(mode="json") used by the endpoint caller is also worth addressing.

Confidence Score: 3/5

  • Mergeable after confirming the additionalProperties truthiness issue in masking_util.py does not silently drop extra fields in production.
  • The core schema change is clean and well-tested at the Pydantic level. However, the masking utility fix depends on whether Pydantic v2.12.4 generates a truthy additionalProperties value — a property not verified by the existing tests. There is no integration test that exercises the full schema-generation → masking pipeline for jira_ticket. If Pydantic generates {} (falsy), extra fields are silently dropped in API responses even though they are preserved in the DB, creating a subtle data-visibility bug. The unrelated and undocumented messaging.py change adds additional uncertainty.
  • src/fides/api/util/masking_util.py — the allows_additional check may be broken by Pydantic v2's actual additionalProperties output format for extra="allow" schemas.

Important Files Changed

Filename Overview
src/fides/api/schemas/connection_configuration/connection_secrets_jira_ticket.py Adds model_config = ConfigDict(extra="allow") to JiraTicketSchema — the stated purpose of this PR. The change is minimal and correctly scoped to this schema only, leaving all other FidesSchema subclasses unaffected. Docstring is updated appropriately.
src/fides/api/util/masking_util.py Adds logic to preserve non-schema fields when additionalProperties is truthy. However, whether the actual Pydantic-generated schema for JiraTicketSchema contains a truthy additionalProperties value is unverified — Pydantic v2 with extra="allow" may generate {} (empty dict, falsy in Python) rather than boolean True, which would silently break the preservation logic.
tests/ops/schemas/connection_configuration/test_connection_config.py Adds a test for the new mask_sensitive_fields behavior using a hand-crafted schema with "additionalProperties": True. Missing an integration test that exercises the full pipeline using the actual JiraTicketSchema.model_json_schema() output to confirm the two halves of this fix work together.
src/fides/api/models/messaging.py Adds model_dump() serialization before storing messaging secrets. This is a correct change (seed.py passes Pydantic model instances directly), but the change is unrelated to the stated PR purpose and goes unmentioned in the PR description.
tests/service/test_jira_ticket_connection.py Renames test_extra_fields_ignored to test_extra_fields_preserved and updates assertions to match the new extra="allow" behavior. Test is clean and accurate.

Last reviewed commit: 75a2a4f

Comment on lines 31 to +43
@@ -27,5 +37,9 @@ def mask_sensitive_fields(
new_connection_secrets[key] = "**********"
else:
new_connection_secrets[key] = value
elif allows_additional:
# Preserve non-schema fields only when the schema explicitly
# allows additional properties (e.g. extra="allow").
new_connection_secrets[key] = value
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.

additionalProperties truthiness may not match Pydantic v2 output

The test for this new branch uses a hand-crafted schema with "additionalProperties": True (Python bool), but Pydantic v2 with extra="allow" generates "additionalProperties": {} (an empty dict) in its model_json_schema() output. In Python bool({}) evaluates to False, so elif allows_additional: would never execute when the schema is obtained via get_connection_type_secret_schema("jira_ticket").

This means the extra fields (like project_key, summary_template) would be silently dropped from the masked secrets in API responses, even though they are preserved in JiraTicketSchema instances and in the database.

The fix should guard against both the boolean and the empty-dict form that Pydantic v2 produces:

raw_additional = secret_schema.get("additionalProperties")
# Pydantic v2 extra="allow" → {} (empty dict, truthy-intended but falsy in Python)
# Pydantic v2 extra="forbid" → False
# hand-crafted schemas → True or False
allows_additional = raw_additional is not False and raw_additional is not None

And an integration test should validate the full pipeline — calling get_connection_type_secret_schema("jira_ticket") and feeding its output into mask_sensitive_fields alongside extra fields — to confirm both halves of the fix compose correctly.

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.

@JadeCara does greptile have a point here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified against the actual runtime: Pydantic 2.12.4 with extra="allow" generates additionalProperties: True (boolean) in JiraTicketSchema.model_json_schema(), not {}. The truthiness check works correctly.

@JadeCara JadeCara requested a review from erosselli March 10, 2026 16:11
Copy link
Copy Markdown
Contributor

@erosselli erosselli left a comment

Choose a reason for hiding this comment

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

approved with some comments

Comment on lines +155 to +159
self.secrets = (
messaging_secrets.model_dump()
if hasattr(messaging_secrets, "model_dump")
else messaging_secrets
)
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.

is this change needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed from this PR — the real fix is updating the seeding in fidesplus so it doesn't pass model instances directly.

Comment on lines 31 to +43
@@ -27,5 +37,9 @@ def mask_sensitive_fields(
new_connection_secrets[key] = "**********"
else:
new_connection_secrets[key] = value
elif allows_additional:
# Preserve non-schema fields only when the schema explicitly
# allows additional properties (e.g. extra="allow").
new_connection_secrets[key] = value
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.

@JadeCara does greptile have a point here?

@@ -0,0 +1,4 @@
type: Changed
description: Allowed extra fields in JiraTicketSchema for Fidesplus extensibility
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.

instead of "for Fidesplus extensibility" can we say why the extra fields are needed, e/g "for preserving ticket metadata" or whatever

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated — made the description more specific about what the extra fields are for.

Jade Wibbels and others added 2 commits March 10, 2026 10:31
- Revert unrelated model_dump() change in messaging.py
- Update changelog description to be more specific about extra fields purpose

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JadeCara JadeCara enabled auto-merge March 10, 2026 16:36
@JadeCara JadeCara added this pull request to the merge queue Mar 10, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 10, 2026
@JadeCara JadeCara added this pull request to the merge queue Mar 16, 2026
Merged via the queue into main with commit 8e3ba9e Mar 16, 2026
58 checks passed
@JadeCara JadeCara deleted the ENG-2539/jira-secrets-extra-allow branch March 16, 2026 18:07
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