Skip to content

fix: propagate @external interface object fields#2145

Merged
Aenimus merged 5 commits intomainfrom
david/eng-7924-interface-object-fields-should-propagate-external
Aug 18, 2025
Merged

fix: propagate @external interface object fields#2145
Aenimus merged 5 commits intomainfrom
david/eng-7924-interface-object-fields-should-propagate-external

Conversation

@Aenimus
Copy link
Copy Markdown
Member

@Aenimus Aenimus commented Aug 15, 2025

Summary by CodeRabbit

  • New Features

    • Clearer, more explicit errors for undefined entity-interface implementations showing per-subgraph defined vs required concrete types.
    • Improved propagation of external fields so Interface Object fields can satisfy implementations across subgraphs.
    • Added a public constant for the interface identifier.
  • Refactor

    • Public error/type shapes changed: concrete-type field renamed/split into defined vs required; consumers may need to adapt.
  • Tests

    • Expanded multi‑subgraph tests covering propagation and error scenarios.

Checklist

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 15, 2025

Walkthrough

Tracks per-subgraph defined and required concrete types for entity interfaces, renames concreteTypeNames to definedConcreteTypeNames in error payloads and types, adds requiredConcreteTypeNames, propagates external field data into existing field data, and updates tests and error messages to use the new shapes and INTERFACE constant.

Changes

Cohort / File(s) Summary
Error construction and messaging
composition/src/errors/errors.ts
Expanded undefinedEntityInterfaceImplementationsError message text and updated destructuring/usage to read per-subgraph definedConcreteTypeNames (replacing concreteTypeNames) in message composition.
Public federation types
composition/src/utils/types.ts
InvalidEntityInterface signature changed: removed concreteTypeNames, added definedConcreteTypeNames: Set<string> and requiredConcreteTypeNames: Set<string> (public API/type surface updated).
Federation factory logic
composition/src/v1/federation/federation-factory.ts
Added SubgraphName import; introduced definedConcreteTypeNamesBySubgraphName; merge per-subgraph definedConcreteTypeNames into subgraph data; propagate externalFieldDataBySubgraphName into existing field data; populate invalid-interface entries with definedConcreteTypeNames and requiredConcreteTypeNames; perform cross-subgraph intersection/validation and report updated errors.
Tests — interface-object scenarios
composition/tests/v1/directives/interface-object.test.ts
Added/used new exports/types (EntityInterfaceFederationData, EntityInterfaceSubgraphData, InvalidEntityInterface, SimpleFieldData, undefinedEntityInterfaceImplementationsError); expanded multi-subgraph fixtures; added assertions for @external propagation and interface/object error cases.
Tests — entity interface validation
composition/tests/v1/entity-interface.test.ts
Tests now import INTERFACE constant; expect invalid-interface payloads to contain definedConcreteTypeNames; updated assertions to inspect returned errors shape and keys.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e8429ca and c9cfa9a.

📒 Files selected for processing (1)
  • composition/src/errors/errors.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • composition/src/errors/errors.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: integration_test (./events)
  • GitHub Check: integration_test (./telemetry)
  • GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
  • GitHub Check: build_test
  • GitHub Check: build_push_image
  • GitHub Check: build_test
  • GitHub Check: Analyze (go)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch david/eng-7924-interface-object-fields-should-propagate-external

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Aug 15, 2025

Router-nonroot image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-453d0c93847e1b7120e0c69c916f24f18d466973-nonroot

Copy link
Copy Markdown
Contributor

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c51be85 and 3b2429b.

📒 Files selected for processing (5)
  • composition/src/errors/errors.ts (2 hunks)
  • composition/src/utils/types.ts (1 hunks)
  • composition/src/v1/federation/federation-factory.ts (5 hunks)
  • composition/tests/v1/directives/interface-object.test.ts (3 hunks)
  • composition/tests/v1/entity-interface.test.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
composition/src/errors/errors.ts (1)
composition/src/utils/utils.ts (1)
  • getEntriesNotInHashSet (31-39)
composition/src/v1/federation/federation-factory.ts (3)
composition/src/types/types.ts (2)
  • SubgraphName (7-7)
  • TypeName (9-9)
composition/src/utils/utils.ts (2)
  • getValueOrDefault (141-149)
  • addIterableValuesToSet (56-60)
composition/src/utils/types.ts (1)
  • InvalidEntityInterface (39-43)
composition/tests/v1/directives/interface-object.test.ts (6)
composition/tests/utils/utils.ts (4)
  • federateSubgraphsSuccess (59-72)
  • schemaToSortedNormalizedString (27-29)
  • normalizeString (19-21)
  • federateSubgraphsFailure (49-57)
composition/src/router-compatibility-version/router-compatibility-version.ts (1)
  • ROUTER_COMPATIBILITY_VERSION_ONE (3-3)
composition/src/errors/errors.ts (1)
  • undefinedEntityInterfaceImplementationsError (845-877)
composition/src/utils/types.ts (1)
  • InvalidEntityInterface (39-43)
composition/src/schema-building/types.ts (3)
  • EntityInterfaceFederationData (319-327)
  • SimpleFieldData (274-277)
  • EntityInterfaceSubgraphData (279-287)
composition/src/ast/utils.ts (1)
  • parse (272-274)
composition/tests/v1/entity-interface.test.ts (6)
composition/tests/utils/utils.ts (1)
  • federateSubgraphsFailure (49-57)
composition/src/router-compatibility-version/router-compatibility-version.ts (1)
  • ROUTER_COMPATIBILITY_VERSION_ONE (3-3)
composition/src/errors/errors.ts (1)
  • undefinedEntityInterfaceImplementationsError (845-877)
composition/src/utils/types.ts (1)
  • InvalidEntityInterface (39-43)
composition/src/utils/string-constants.ts (1)
  • INTERFACE (71-71)
composition/src/schema-building/types.ts (1)
  • EntityInterfaceFederationData (319-327)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: build_push_image
  • GitHub Check: build_test
  • GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
  • GitHub Check: integration_test (./telemetry)
  • GitHub Check: integration_test (./events)
  • GitHub Check: build_test
  • GitHub Check: build_test
  • GitHub Check: Analyze (go)
🔇 Additional comments (9)
composition/src/utils/types.ts (1)

40-43: Type shape change aligns with per-subgraph semantics

Replacing concreteTypeNames with definedConcreteTypeNames and requiredConcreteTypeNames makes the error payload precise and actionable per subgraph. This matches downstream usages in errors and federation-factory. LGTM.

composition/src/errors/errors.ts (1)

868-874: Correct switch-over to definedConcreteTypeNames

Using definedConcreteTypeNames in disparity computation is consistent with the new InvalidEntityInterface payload. This ensures we report exactly the implementations absent from a subgraph's explicit or propagated (via interface objects) definitions.

composition/src/v1/federation/federation-factory.ts (3)

3071-3080: Good: Track concrete types defined per subgraph (incl. interface-object propagation)

Building definedConcreteTypeNamesBySubgraphName and aggregating both the subgraph’s own concrete types and those implied via @interfaceObject ensures later validation can account for “provided” implementations, not just local definitions.


3082-3091: Good: InvalidEntityInterface now carries defined vs required sets

Populating definedConcreteTypeNames and requiredConcreteTypeNames makes the downstream error useful and aligns with type changes. The resolvable gate prevents false positives when resolvable: false.


1660-1686: Propagating @external and @Shareable from Interface Object to implementations is correct

Setting isShareableBySubgraphName, adding the subgraph to subgraphNames, and copying externalFieldDataBySubgraphName only when defined avoids inadvertently marking fields as external. This matches the goal: allow interface-object-provided externals to satisfy interface contracts on concrete types.

composition/tests/v1/entity-interface.test.ts (1)

146-183: Tests align with new error payload and INTERFACE key

Switching to destructured { errors }, using the public INTERFACE symbol, and asserting definedConcreteTypeNames/requiredConcreteTypeNames makes the test robust to the new API. Looks good.

composition/tests/v1/directives/interface-object.test.ts (3)

4-21: Import shape updates reflect public API evolution

Bringing in EntityInterfaceFederationData, EntityInterfaceSubgraphData, InvalidEntityInterface, SimpleFieldData, INTERFACE, and the error factory ensures tests remain tightly coupled to the exported API surface. Good coverage.


684-716: Excellent: Validates propagation of @external fields from Interface Object to implementations (entity-interface chain)

This scenario ensures fields required by EntityInterfaceB (via @interfaceObject) propagate to the concrete Entity and satisfy both EntityInterfaceA and EntityInterfaceB. This is a high-value regression test for the fix.


752-785: Error-path test correctly asserts per-subgraph defined vs required implementations

Verifying undefinedEntityInterfaceImplementationsError with definedConcreteTypeNames and requiredConcreteTypeNames confirms the new error semantics—particularly when no Interface Object in the subgraph provides the missing implementations.

Comment thread composition/src/errors/errors.ts Outdated
Comment thread composition/src/v1/federation/federation-factory.ts
Copy link
Copy Markdown
Contributor

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

♻️ Duplicate comments (1)
composition/src/v1/federation/federation-factory.ts (1)

3113-3132: Bug: .intersection is not a function on Set — runtime failure

Native Set in JS/TS doesn’t implement intersection. This line will throw. Compute the intersection via filtering instead.

Apply this diff:

-      const definedTypeNames = invalidInterface.requiredConcreteTypeNames.intersection(validTypeNames);
+      const definedTypeNames = new Set<TypeName>(
+        [...invalidInterface.requiredConcreteTypeNames].filter((t) => validTypeNames.has(t)),
+      );

Optionally verify no other usages of Set.prototype.intersection remain:

#!/bin/bash
# Find any remaining uses of Set.prototype.intersection in the repo with context
rg -nPU '\.intersection\s*\(' -C3
🧹 Nitpick comments (1)
composition/src/v1/federation/federation-factory.ts (1)

1676-1686: Avoid overwriting shareability to false when not explicitly set

When propagating @Shareable from the Interface Object field to an existing concrete field, defaulting missing entries to false can inadvertently downgrade previously true values for that subgraph. Only set the value when the source map explicitly has the subgraph entry.

Apply this diff:

-              const isShareable = fieldData.isShareableBySubgraphName.get(subgraphName) ?? false;
-              existingFieldData.isShareableBySubgraphName.set(subgraphName, isShareable);
+              if (fieldData.isShareableBySubgraphName.has(subgraphName)) {
+                existingFieldData.isShareableBySubgraphName.set(
+                  subgraphName,
+                  fieldData.isShareableBySubgraphName.get(subgraphName)!,
+                );
+              }
               existingFieldData.subgraphNames.add(subgraphName);
               const externalData = fieldData.externalFieldDataBySubgraphName.get(subgraphName);
               if (!externalData) {
                 continue;
               }
               existingFieldData.externalFieldDataBySubgraphName.set(subgraphName, { ...externalData });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3b2429b and e8429ca.

📒 Files selected for processing (2)
  • composition/src/errors/errors.ts (2 hunks)
  • composition/src/v1/federation/federation-factory.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • composition/src/errors/errors.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
composition/src/v1/federation/federation-factory.ts (4)
composition/src/types/types.ts (2)
  • SubgraphName (7-7)
  • TypeName (9-9)
controlplane/src/core/util.ts (1)
  • getValueOrDefault (391-399)
composition/src/utils/utils.ts (2)
  • getValueOrDefault (141-149)
  • addIterableValuesToSet (56-60)
composition/src/utils/types.ts (1)
  • InvalidEntityInterface (39-43)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: build_push_image
  • GitHub Check: build_push_image (nonroot)
  • GitHub Check: image_scan (nonroot)
  • GitHub Check: image_scan
  • GitHub Check: integration_test (./telemetry)
  • GitHub Check: integration_test (./events)
  • GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
  • GitHub Check: build_test
  • GitHub Check: build_test
  • GitHub Check: build_push_image
  • GitHub Check: build_test
  • GitHub Check: build_push_image
  • GitHub Check: build_test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (3)
composition/src/v1/federation/federation-factory.ts (3)

233-234: Import additions align with new per-subgraph tracking

Importing SubgraphName and TypeName is consistent with the new per-subgraph type tracking introduced later in the file.


1620-1620: Comment clarification LGTM

The updated comment improves intent clarity around propagating Interface Object subgraph locations to implementing concrete types.


3070-3095: Per-subgraph defined concrete types accumulation looks sound

Tracking definedConcreteTypeNamesBySubgraphName and populating it while iterating per-interface/per-subgraph data is consistent with the later cross-subgraph validation pass. The InvalidEntityInterface payload updates (definedConcreteTypeNames/requiredConcreteTypeNames) align with the type changes.

Copy link
Copy Markdown
Contributor

@StarpTech StarpTech left a comment

Choose a reason for hiding this comment

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

LGTM

@Aenimus Aenimus enabled auto-merge (squash) August 18, 2025 09:41
@Aenimus Aenimus merged commit 783f875 into main Aug 18, 2025
33 checks passed
@Aenimus Aenimus deleted the david/eng-7924-interface-object-fields-should-propagate-external branch August 18, 2025 09:48
@Noroth Noroth mentioned this pull request Sep 30, 2025
5 tasks
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