Skip to content

ENG-2799: Support many:one integration-to-system relationship#7555

Merged
adamsachs merged 11 commits intomainfrom
asachs/ENG-2799
Mar 6, 2026
Merged

ENG-2799: Support many:one integration-to-system relationship#7555
adamsachs merged 11 commits intomainfrom
asachs/ENG-2799

Conversation

@adamsachs
Copy link
Contributor

@adamsachs adamsachs commented Mar 3, 2026

Ticket ENG-2799

Description Of Changes

Change System.connection_configs from a scalar (uselist=False) to a list (uselist=True) so the ORM, schema, API endpoints, and frontend all correctly handle multiple integrations per system.

The join table (system_connection_config_link) already supports many:one — this change propagates list semantics through every layer. No new migrations required.

This is a breaking API change: connection_configs in the system response is now an array instead of a single object. External consumers expecting a dict will need to update.

Note: our System > Integrations tab for a given system will stay showing one integration, as it does today, for simplicity and to keep this changed scoped. the UI will simply use the 'first' connection config information, ordered by the connection config (integration)'s created date (first created shows first). we do have a followup effort planned to update that UX to show the potentially many integrations associated with a given system.

#7557 is a followup to handle a change to consent tracking status.

Code Changes

  • src/fides/api/models/sql_models.py - Change uselist=Falseuselist=True on System.connection_configs relationship
  • src/fides/api/schemas/system.py - Change connection_configs type from Optional[ConnectionConfigurationResponse]Optional[List[ConnectionConfigurationResponse]]
  • src/fides/api/api/v1/endpoints/system.py - Update deprecated patch_connection_secrets and delete_connection endpoints to guard for empty list and use [0] indexing
  • clients/admin-ui/src/features/data-catalog/systems/CatalogSystemsTable.tsx - Update 3 scalar access patterns to ?.[0]?.key
  • clients/admin-ui/src/features/system/hooks/useSystemFormTabs.tsx - Pass connection_configs?.[0] ?? null to ConnectionForm, update key access
  • clients/admin-ui/src/pages/systems/configure/[id]/test-datasets.tsx - Update scalar .key access to ?.[0]?.key
  • clients/admin-ui/src/types/api/models/SystemResponse.ts - Update TS type to Array<ConnectionConfigurationResponse> | null
  • clients/admin-ui/src/types/api/models/SystemResponseExtended.ts - Same type update
  • clients/admin-ui/src/types/api/models/SystemWithMonitorKeys.ts - Same type update
  • clients/privacy-center/types/api/models/SystemResponse.ts - Same type update
  • clients/admin-ui/cypress/fixtures/systems/system_active_integration.json - Wrap fixture connection_configs in array
  • clients/admin-ui/cypress/fixtures/systems/system_disabled_integration.json - Wrap fixture connection_configs in array
  • clients/admin-ui/cypress/fixtures/data-catalog/catalog-systems.json - Wrap fixture connection_configs in arrays
  • tests/ops/api/v1/endpoints/test_system.py - Update .connection_configs.key.connection_configs[0].key

Steps to Confirm

  1. nox -s static_checks passes (ruff check, ruff format, mypy — all clean)
  2. grep -rn "\.connection_configs\." src/ tests/ shows no remaining scalar access patterns
  3. TypeScript types show Array<ConnectionConfigurationResponse> | null
  4. Manual smoke test: create a system, link 2 integrations via the join table, GET /system/{fides_key} returns both in a list

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:
    • Followup issues created
      • Consent status tracking race condition (keyed by system_key, not per-connection)
      • New UI for managing multiple integrations per system
      • Fidesplus test updates (separate PR after dependency bump)
    • No followup issues
  • Database migrations:
    • No migrations
  • Documentation:

Summary by CodeRabbit

  • New Features

    • Systems now support multiple connection configurations, enabling many-to-one integrations.
  • Bug Fixes

    • UI and APIs now safely handle absent or multiple connection configurations and surface clearer errors when none exist.
  • Tests

    • Added tests verifying multiple connection configurations are returned and ordered.
  • Documentation

    • Added changelog entry describing the many-to-one connection_configs change.

adamsachs and others added 4 commits March 3, 2026 10:31
- Remove lazy-load footgun in from_orm; pass system info explicitly via SQL joins
- Return lightweight ref entities from resolve_connection_config/resolve_system
- Add SystemLinkResponse.from_entity() to reduce route handler duplication
- Move TooManyLinksError check after connection config lookup in set_links
- Remove empty __table_args__ from SystemConnectionConfigLink model
- Remove unnecessary cleanup_links autouse fixtures from tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ype annotation

- Use outerjoin instead of inner join so links with deleted systems
  are still returned (with None system info) rather than silently dropped
- Make _to_entity_with_system an instance method (called via self)
- Remove unnecessary string forward reference on SystemRef type

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change System.connection_configs from a scalar (uselist=False) to a list
(uselist=True) so the ORM, schema, API endpoints, and frontend all
correctly handle multiple integrations per system. The join table already
supports this — this change propagates the list semantics through every
layer.

No new migrations required.

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

vercel bot commented Mar 3, 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 Mar 6, 2026 11:45am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
fides-privacy-center Ignored Ignored Mar 6, 2026 11:45am

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 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: 3eb5184f-b1fa-4cd4-af31-01d4507363fd

📥 Commits

Reviewing files that changed from the base of the PR and between 750b915 and 84cf486.

📒 Files selected for processing (4)
  • changelog/7555-many-one-integration-system.yaml
  • src/fides/api/api/v1/endpoints/system.py
  • src/fides/api/models/sql_models.py
  • tests/ctl/core/test_api.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/fides/api/api/v1/endpoints/system.py
  • changelog/7555-many-one-integration-system.yaml

📝 Walkthrough

Walkthrough

Converts System.connection_configs from a single object to a list throughout the codebase; updates DB model, API endpoints, type definitions, fixtures, frontend access patterns, and tests to use array semantics and to operate on the first connection config when needed.

Changes

Cohort / File(s) Summary
Changelog
changelog/7555-many-one-integration-system.yaml
Added entry documenting change from scalar to list for System.connection_configs.
DB Model
src/fides/api/models/sql_models.py
Changed System.connection_configs relationship from uselist=False to uselist=True and added ordering by ConnectionConfig.created_at.
Backend API
src/fides/api/api/v1/endpoints/system.py, src/fides/api/schemas/system.py
Endpoints and schema updated to expect a list; endpoints now error when no linked configs and operate on connection_configs[0].key (oldest).
Frontend Types
clients/admin-ui/src/types/api/models/SystemResponse.ts, clients/admin-ui/src/types/api/models/SystemResponseExtended.ts, clients/admin-ui/src/types/api/models/SystemWithMonitorKeys.ts, clients/privacy-center/types/api/models/SystemResponse.ts
Updated connection_configs type from a single `ConnectionConfigurationResponse
Frontend Components & Hooks
clients/admin-ui/src/features/data-catalog/systems/CatalogSystemsTable.tsx, clients/admin-ui/src/features/system/hooks/useSystemFormTabs.tsx, clients/admin-ui/src/pages/systems/configure/[id]/test-datasets.tsx
Replaced scalar access with safe first-item access (connection_configs?.[0] / ?.[0]?.key) for UI behavior, props, and key derivation.
Fixtures
clients/admin-ui/cypress/fixtures/data-catalog/catalog-systems.json, clients/admin-ui/cypress/fixtures/systems/system_active_integration.json, clients/admin-ui/cypress/fixtures/systems/system_disabled_integration.json
Restructured connection_configs from an object to an array containing one object in test fixtures.
Tests
tests/ctl/core/test_api.py, tests/ops/api/v1/endpoints/test_system.py
Adjusted expectations to treat connection_configs as an empty list by default; added test for multiple connection configs and updated cached-key access to use [0].key.

Sequence Diagram(s)

sequenceDiagram
  participant Frontend
  participant API
  participant DB
  Frontend->>API: Request system details
  API->>DB: Query System with connection_configs (ordered by created_at)
  DB-->>API: System + list(connection_configs)
  API-->>Frontend: SystemResponse (connection_configs: [...])
  Frontend->>Frontend: Use connection_configs?.[0]?.key for UI actions
  Frontend->>API: PATCH /systems/:id/connection_secrets (uses first config key)
  API->>DB: Update secrets for ConnectionConfig.key = connection_configs[0].key
  DB-->>API: Success
  API-->>Frontend: 200 OK
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • galvana
  • JadeCara

Poem

🐰 From single burrow to a cozy row,
Many configs now hop and grow.
I nibble the first, the oldest seed,
Order kept, no frantic speed,
Hooray — more friends for each system to know! 🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% 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 describes the main change: converting the system-to-connection relationship from scalar to support many:one (multiple integrations per system).
Description check ✅ Passed The description is comprehensive and well-structured, covering the change rationale, breaking API change notice, code changes across backend and frontend, validation steps, and pre-merge checklist progress.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch asachs/ENG-2799

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

Guard against undefined connection_config_key in CatalogSystemsTable
and update test assertion to expect [] instead of None for the now
list-valued connection_configs relationship.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
adamsachs and others added 2 commits March 4, 2026 20:49
Copy link
Contributor Author

@adamsachs adamsachs left a comment

Choose a reason for hiding this comment

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

some self-review notes, at least one thing i need to circle back to:

type: Changed
description: Changed System.connection_configs from scalar to list for many:one support
pr: 7555
labels: ["high-risk"]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

eh, claude thought this was high-risk but i think i'll probably remove this label

Suggested change
labels: ["high-risk"]
labels: []

</Box>
<ConnectionForm
connectionConfig={activeSystem.connection_configs}
connectionConfig={activeSystem.connection_configs?.[0] ?? null}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we keep this functionality the same on the FE for now - we simply choose the 'first' integration back from the API. this is to limit the scope of the change for now, and we have a followup effort to update this UX.

return update_connection_secrets(
connection_service,
system.connection_configs.key,
system.connection_configs[0].key,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm. looking at this more closely, i think this could introduce a potential bug with the FE integration: if the 'first' integration coming back on the 'get_system_connections` endpoint response is not the same as this 'first' integration that gets chosen here on the secret update, someone using the UI to update secrets could actually update secrets of a different connection.

the source of the issue here is clear: we're continuing to try and support this particular UX that treats this as only a single connection/integration per system, but on the BE we can have many.

i'll think a bit about how to ensure this discrepancy doesn't occur for now, in a targeted way, until we change/improve that UX...

Copy link
Contributor

Choose a reason for hiding this comment

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

Would it help if we made the ordering of the connection configs deterministic (e.g. always ordering by created_at)? That might ensure the "first" connection is consistent between the get_system_connections response and the secret update.

Maybe as a temporary mitigation until we improve the UX around multiple connections per system

@adamsachs adamsachs marked this pull request as ready for review March 5, 2026 15:58
@adamsachs adamsachs requested review from a team as code owners March 5, 2026 15:58
@adamsachs adamsachs requested review from gilluminate and thabofletcher and removed request for a team March 5, 2026 15:58
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 5, 2026

Greptile Summary

This PR propagates the System.connection_configs many-to-one semantics through every layer of the stack — ORM (uselist=True), Pydantic schema (Optional[List[...]]), TypeScript types, API endpoints, frontend hooks, and test fixtures — without requiring a database migration since the join table already supported multiple links. It is a breaking API change: connection_configs in the system response changes from a single object to an array.

Key changes and observations:

  • ORM / Schema / Types: The single-line uselist=Falseuselist=True flip correctly unlocks the already-existing many-to-one join table capability. All TypeScript model types (SystemResponse, SystemResponseExtended, SystemWithMonitorKeys) and the privacy-center type are updated in sync.
  • Frontend: All scalar connection_configs.key accesses are updated to connection_configs?.[0]?.key optional chaining. The UI intentionally continues showing only the first integration per the PR description.
  • Deprecated endpoints: delete_connection and patch_connection_secrets now use connection_configs[0] indexing, silently operating only on the first linked config when there may be multiple. The old placeholder comment explaining this was removed; the behavior limitation is not reflected in the endpoint docstrings.
  • Test coverage: Existing tests are updated to use [0] indexing but no new test exercises the newly enabled multi-config scenario (e.g. a system with 2 linked integrations returning both in a list from GET /system/{fides_key}).
  • PR size: This PR touches 16 files, exceeding the 15-file threshold in the team's custom PR size guideline.

Confidence Score: 3/5

  • Safe to merge with minor documentation and test coverage gaps; deprecated-endpoint behavior with multiple configs should be noted.
  • The core ORM/schema/type changes are minimal and correct. The main concerns are: (1) deprecated endpoints silently operating on only the first of potentially many configs without documenting this in the docstring, and (2) no new test exercising the actual many-to-one scenario that is the purpose of this PR. The PR also exceeds the 15-file team guideline.
  • src/fides/api/api/v1/endpoints/system.py (deprecated endpoint behavior with multiple configs), tests/ops/api/v1/endpoints/test_system.py (missing multi-config coverage)

Important Files Changed

Filename Overview
src/fides/api/models/sql_models.py Changes uselist=False to uselist=True on the connection_configs ORM relationship — minimal, correct, no migration required since the join table already supported many-to-one.
src/fides/api/schemas/system.py Updates connection_configs from Optional[ConnectionConfigurationResponse] to Optional[List[ConnectionConfigurationResponse]] — straightforward and consistent with the ORM change.
src/fides/api/api/v1/endpoints/system.py Deprecated endpoints patch_connection_secrets and delete_connection now silently operate only on connection_configs[0] when multiple configs may exist; the old placeholder comment was removed but the limitation is undocumented in the docstrings.
clients/admin-ui/src/features/data-catalog/systems/CatalogSystemsTable.tsx Updates three scalar access patterns to use ?.[0]?.key optional chaining; also adds a defensive guard in handleRowClicked when no connection config exists (though getRowIsClickable already prevents this path from being hit).
tests/ops/api/v1/endpoints/test_system.py Updates connection_configs.key to connection_configs[0].key — correct for single-config tests, but no new test is added to cover the many-config scenario that is the core purpose of this PR.

Comments Outside Diff (2)

  1. src/fides/api/api/v1/endpoints/system.py, line 227-241 (link)

    Deprecated endpoints silently operate on first config only

    Both delete_connection and patch_connection_secrets now use connection_configs[0] indexing, meaning when a system has multiple configs they silently operate only on the first one. The old placeholder comment (# system.connection_configs will temporarily only have one config) was removed, but the limitation remains.

    Since these are deprecated endpoints, this is an acceptable tradeoff, but the docstrings should be updated to reflect this behavior so callers aren't surprised. For example:

        """Delete the connection config linked to this system.
    
        Deprecated: Use DELETE /connection/{connection_key} to delete a connection
        config, or DELETE /connection/{connection_key}/system-links/{system_fides_key}
        to unlink it from a system without deleting it.
    
        Note: if multiple integrations are linked to this system, only the first one
        will be deleted.
        """

    The same applies to patch_connection_secrets at line 191.

  2. tests/ops/api/v1/endpoints/test_system.py, line 547-562 (link)

    No multi-config test coverage added

    The core goal of this PR is to support a many-to-one integration-to-system relationship, but there are no new tests that exercise the case where a system has 2+ connection configs. The existing tests only verify single-config behavior (updated to use [0] indexing).

    It would be valuable to add at least one test that:

    1. Links 2 connection configs to a system via the join table
    2. Calls GET /system/{fides_key} and asserts connection_configs is a list of 2 items
    3. (Optionally) verifies the deprecated DELETE endpoint operates only on the first config

    This would provide a regression baseline for the new many-to-one semantics.

Last reviewed commit: 750b915

Copy link

@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: 3

♻️ Duplicate comments (1)
src/fides/api/api/v1/endpoints/system.py (1)

202-209: ⚠️ Potential issue | 🔴 Critical

Block ambiguous first-item mutation/deletion when multiple integrations exist.

Line 209 and Line 241 implicitly target connection_configs[0]. With multiple linked configs, this can patch/delete the wrong integration.

🛠️ Proposed fix
 def patch_connection_secrets(
@@
     if not system.connection_configs:
         raise HTTPException(
             status_code=HTTP_404_NOT_FOUND,
             detail="No integration found linked to this system",
         )
+    if len(system.connection_configs) > 1:
+        raise HTTPException(
+            status_code=status.HTTP_409_CONFLICT,
+            detail=(
+                "Multiple integrations are linked to this system. "
+                "Use PATCH /connection/{connection_key}/secret."
+            ),
+        )
     return update_connection_secrets(
         connection_service,
         system.connection_configs[0].key,
@@
 def delete_connection(fides_key: str, *, db: Session = Depends(deps.get_db)) -> None:
@@
     if not system.connection_configs:
         raise HTTPException(
             status_code=HTTP_404_NOT_FOUND,
             detail="No integration found linked to this system",
         )
+    if len(system.connection_configs) > 1:
+        raise HTTPException(
+            status_code=status.HTTP_409_CONFLICT,
+            detail=(
+                "Multiple integrations are linked to this system. "
+                "Use DELETE /connection/{connection_key} or system-links endpoints."
+            ),
+        )
 
     delete_connection_config(db, system.connection_configs[0].key)

Also applies to: 235-241

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/fides/api/api/v1/endpoints/system.py` around lines 202 - 209, The code
currently assumes the first linked config (system.connection_configs[0]) when
calling update_connection_secrets and when deleting, which can mutate/delete the
wrong integration if multiple configs exist; update the endpoints (calls to
update_connection_secrets and the delete logic) to require an unambiguous
selection: if len(system.connection_configs) > 1, return an HTTP 400/422 asking
for an explicit connection key or accept and validate a supplied connection_key
parameter, otherwise proceed using the single config; validate the chosen key
exists in system.connection_configs (match by .key) before calling
update_connection_secrets or delete_connection_config to avoid accidentally
operating on the wrong config.
🧹 Nitpick comments (1)
tests/ops/api/v1/endpoints/test_system.py (1)

557-559: Add a multi-link delete test to lock expected selection semantics.

This assertion now depends on first-item selection. Please add one test with 2 linked configs to explicitly define which config should be deleted when calling the system-level delete endpoint.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/ops/api/v1/endpoints/test_system.py` around lines 557 - 559, Add a new
test (e.g., test_system_multi_link_delete_selection_semantics) that constructs a
system with two linked connection configs by appending a second config to
system_linked_with_oauth2_authorization_code_connection_config.connection_configs,
capture both keys (connection_configs[0].key and connection_configs[1].key),
invoke the system-level delete endpoint the same way the existing test does, and
assert that the deleted config is the expected one (explicitly assert which key
was removed and that the remaining connection_configs contains the other key) to
lock the first-item selection behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@clients/admin-ui/cypress/fixtures/systems/system_active_integration.json`:
- Around line 47-71: Replace internal/system-specific identifiers and
non-reserved domains in the connection_configs fixture: change the "key" value
("fidesctl_system_iterable_api") and "saas_config.fides_key" to a generic
placeholder (e.g., "example_system_iterable" or "example_saas_key"), and update
"secrets.domain" ("api.iterable.com") to an RFC 2606 reserved example domain
like "api.example.com" or "example.com"; keep the "secrets.api_key" masked
(**********) and leave other fields intact so tests still reflect a saas
connection with enabled erasure action.

In `@clients/admin-ui/cypress/fixtures/systems/system_disabled_integration.json`:
- Line 56: Replace the non‑RFC2606 hostname in the fixture: in the
system_disabled_integration.json fixture update the "host" JSON field (currently
"host.docker.internal") to an RFC2606 reserved example domain such as
"db.example.com" so the fixture uses an example domain instead of a real
hostname.

In `@src/fides/api/models/sql_models.py`:
- Around line 599-605: The connection_configs relationship on the model is
unordered so using connection_configs[0] can return an arbitrary row; update the
relationship declaration for connection_configs to include an explicit order_by
(e.g., order_by=ConnectionConfig.id or ConnectionConfig.created_at) so the list
is deterministic, ensuring callers like update_connection_secrets and
delete_connection_config in system.py operate on the intended config; modify the
relationship definition that references "ConnectionConfig" to add the order_by
argument and run tests to confirm index-based usages are stable.

---

Duplicate comments:
In `@src/fides/api/api/v1/endpoints/system.py`:
- Around line 202-209: The code currently assumes the first linked config
(system.connection_configs[0]) when calling update_connection_secrets and when
deleting, which can mutate/delete the wrong integration if multiple configs
exist; update the endpoints (calls to update_connection_secrets and the delete
logic) to require an unambiguous selection: if len(system.connection_configs) >
1, return an HTTP 400/422 asking for an explicit connection key or accept and
validate a supplied connection_key parameter, otherwise proceed using the single
config; validate the chosen key exists in system.connection_configs (match by
.key) before calling update_connection_secrets or delete_connection_config to
avoid accidentally operating on the wrong config.

---

Nitpick comments:
In `@tests/ops/api/v1/endpoints/test_system.py`:
- Around line 557-559: Add a new test (e.g.,
test_system_multi_link_delete_selection_semantics) that constructs a system with
two linked connection configs by appending a second config to
system_linked_with_oauth2_authorization_code_connection_config.connection_configs,
capture both keys (connection_configs[0].key and connection_configs[1].key),
invoke the system-level delete endpoint the same way the existing test does, and
assert that the deleted config is the expected one (explicitly assert which key
was removed and that the remaining connection_configs contains the other key) to
lock the first-item selection behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5c25a311-58dc-44c1-af44-65bfa9595a41

📥 Commits

Reviewing files that changed from the base of the PR and between f7b17b5 and 750b915.

📒 Files selected for processing (16)
  • changelog/7555-many-one-integration-system.yaml
  • clients/admin-ui/cypress/fixtures/data-catalog/catalog-systems.json
  • clients/admin-ui/cypress/fixtures/systems/system_active_integration.json
  • clients/admin-ui/cypress/fixtures/systems/system_disabled_integration.json
  • clients/admin-ui/src/features/data-catalog/systems/CatalogSystemsTable.tsx
  • clients/admin-ui/src/features/system/hooks/useSystemFormTabs.tsx
  • clients/admin-ui/src/pages/systems/configure/[id]/test-datasets.tsx
  • clients/admin-ui/src/types/api/models/SystemResponse.ts
  • clients/admin-ui/src/types/api/models/SystemResponseExtended.ts
  • clients/admin-ui/src/types/api/models/SystemWithMonitorKeys.ts
  • clients/privacy-center/types/api/models/SystemResponse.ts
  • src/fides/api/api/v1/endpoints/system.py
  • src/fides/api/models/sql_models.py
  • src/fides/api/schemas/system.py
  • tests/ctl/core/test_api.py
  • tests/ops/api/v1/endpoints/test_system.py

Comment on lines +47 to +71
"connection_configs": [
{
"name": null,
"key": "fidesctl_system_iterable_api",
"description": "",
"connection_type": "saas",
"access": "write",
"created_at": "2024-08-01T20:38:51.953543+00:00",
"updated_at": "2024-08-02T16:07:57.769608+00:00",
"disabled": false,
"last_test_timestamp": "2024-08-02T16:07:58.452157+00:00",
"last_test_succeeded": true,
"saas_config": {
"fides_key": "fidesctl_system_iterable_api",
"name": "Iterable",
"type": "iterable"
},
"secrets": {
"api_key": "**********",
"domain": "api.iterable.com"
},
"authorized": false,
"enabled_actions": ["erasure"]
}
]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Sanitize fixture identifiers and domains to approved placeholders.

This changed block includes non-reserved/example domain data (api.iterable.com) and internal-like system identifiers (fidesctl_system_iterable_api). Please replace with generic placeholders.

🧹 Suggested fixture-safe replacement
-      "key": "fidesctl_system_iterable_api",
+      "key": "example_saas_integration",
...
-        "fides_key": "fidesctl_system_iterable_api",
-        "name": "Iterable",
-        "type": "iterable"
+        "fides_key": "example_saas_integration",
+        "name": "Example SaaS",
+        "type": "example_saas"
...
-        "domain": "api.iterable.com"
+        "domain": "api.example.com"

As per coding guidelines, "Use RFC 2606 reserved domains and subdomains in code examples" and "Do not include internal Ethyca URLs, server names, database names, or system references in code - use generic placeholders or environment variables instead".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"connection_configs": [
{
"name": null,
"key": "fidesctl_system_iterable_api",
"description": "",
"connection_type": "saas",
"access": "write",
"created_at": "2024-08-01T20:38:51.953543+00:00",
"updated_at": "2024-08-02T16:07:57.769608+00:00",
"disabled": false,
"last_test_timestamp": "2024-08-02T16:07:58.452157+00:00",
"last_test_succeeded": true,
"saas_config": {
"fides_key": "fidesctl_system_iterable_api",
"name": "Iterable",
"type": "iterable"
},
"secrets": {
"api_key": "**********",
"domain": "api.iterable.com"
},
"authorized": false,
"enabled_actions": ["erasure"]
}
]
"connection_configs": [
{
"name": null,
"key": "example_saas_integration",
"description": "",
"connection_type": "saas",
"access": "write",
"created_at": "2024-08-01T20:38:51.953543+00:00",
"updated_at": "2024-08-02T16:07:57.769608+00:00",
"disabled": false,
"last_test_timestamp": "2024-08-02T16:07:58.452157+00:00",
"last_test_succeeded": true,
"saas_config": {
"fides_key": "example_saas_integration",
"name": "Example SaaS",
"type": "example_saas"
},
"secrets": {
"api_key": "**********",
"domain": "api.example.com"
},
"authorized": false,
"enabled_actions": ["erasure"]
}
]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/admin-ui/cypress/fixtures/systems/system_active_integration.json`
around lines 47 - 71, Replace internal/system-specific identifiers and
non-reserved domains in the connection_configs fixture: change the "key" value
("fidesctl_system_iterable_api") and "saas_config.fides_key" to a generic
placeholder (e.g., "example_system_iterable" or "example_saas_key"), and update
"secrets.domain" ("api.iterable.com") to an RFC 2606 reserved example domain
like "api.example.com" or "example.com"; keep the "secrets.api_key" masked
(**********) and leave other fields intact so tests still reflect a saas
connection with enabled erasure action.

"last_test_succeeded": null,
"saas_config": null,
"secrets": {
"host": "host.docker.internal",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use an RFC2606-safe hostname in fixture secrets.

host.docker.internal should be replaced with a reserved example domain (for example, db.example.com) in this fixture.

🔧 Proposed fix
-        "host": "host.docker.internal",
+        "host": "db.example.com",
As per coding guidelines, "Use RFC 2606 reserved domains and subdomains in code examples - use `example.com`, `customer.test`, `client.invalid` instead of real domain names".
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"host": "host.docker.internal",
"host": "db.example.com",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/admin-ui/cypress/fixtures/systems/system_disabled_integration.json`
at line 56, Replace the non‑RFC2606 hostname in the fixture: in the
system_disabled_integration.json fixture update the "host" JSON field (currently
"host.docker.internal") to an RFC2606 reserved example domain such as
"db.example.com" so the fixture uses an example domain instead of a real
hostname.

@adamsachs adamsachs requested review from vcruces and removed request for thabofletcher March 5, 2026 16:07
Copy link
Contributor

@gilluminate gilluminate left a comment

Choose a reason for hiding this comment

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

FE looks good!

@adamsachs adamsachs requested a review from galvana March 5, 2026 17:10
Copy link
Contributor

@vcruces vcruces 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 to me! I left a comment that might help mitigate the potential issue you mentioned. Coderabbit suggested the same idea as well

Copy link
Contributor

@vcruces vcruces 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 to me! I left a comment that might help mitigate the potential issue you mentioned. Coderabbit suggested the same idea as well

adamsachs and others added 2 commits March 5, 2026 21:09
- Remove high-risk changelog label
- Add deterministic order_by=created_at to connection_configs relationship
  so connection_configs[0] is always the oldest integration
- Document deprecated endpoint behavior when multiple integrations exist
- Add test for system with multiple connection configs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@adamsachs adamsachs added this pull request to the merge queue Mar 6, 2026
Merged via the queue into main with commit 0807bc9 Mar 6, 2026
62 checks passed
@adamsachs adamsachs deleted the asachs/ENG-2799 branch March 6, 2026 14:32
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