From 8f0a79b119c8cfdae484d4073a598f941b36306e Mon Sep 17 00:00:00 2001 From: Jeff Auriemma Date: Tue, 21 Apr 2026 15:35:21 -0400 Subject: [PATCH 1/3] [DXM-483] Fix "Learn More" link for Connectors 0.3 prerequisite note Update the link on the Federation v2.12 changelog entry to point directly to the Connectors 0.3 section of the connectors changelog, rather than the top of the changelog page. This addresses customer confusion about where to find details on what changed in Connector spec v0.3. --- .../schema-design/federated-schemas/reference/versions.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/schema-design/federated-schemas/reference/versions.mdx b/docs/source/schema-design/federated-schemas/reference/versions.mdx index a0da18bea..9af0f3527 100644 --- a/docs/source/schema-design/federated-schemas/reference/versions.mdx +++ b/docs/source/schema-design/federated-schemas/reference/versions.mdx @@ -46,7 +46,7 @@ Federation v2.13 is a prerequisite for the Connector specification version 0.4. | **November 2025** | **Yes** | **`2.8.0`** | Federation v2.12 is a prerequisite for the Connector specification version 0.3. -[Learn more.](/graphos/connectors/reference/changelog) +[Learn more.](/graphos/connectors/reference/changelog#connectors-03--federation-2120) #### Directive changes From 8200b1541b2218f453eb58f41557b6a67edc642d Mon Sep 17 00:00:00 2001 From: Brianna Fugate Date: Mon, 11 May 2026 11:35:21 -0400 Subject: [PATCH 2/3] update changesets (#3435) Fed 2.14 changeset docs update --- .../federated-schemas/reference/versions.mdx | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/source/schema-design/federated-schemas/reference/versions.mdx b/docs/source/schema-design/federated-schemas/reference/versions.mdx index 9af0f3527..875000940 100644 --- a/docs/source/schema-design/federated-schemas/reference/versions.mdx +++ b/docs/source/schema-design/federated-schemas/reference/versions.mdx @@ -26,6 +26,28 @@ For a comprehensive changelog for Apollo Federation and its associated libraries - If you maintain a [subgraph-compatible library](/graphos/reference/federation/compatible-subgraphs), consult this article to stay current with recently added directives. All of these directive definitions are also listed in the [subgraph specification](/graphos/reference/federation/subgraph-spec/#subgraph-schema-additions). +## v2.14 + +
+ +| First release | Available in GraphOS? | Minimum router version | +| ------------- | --------------------- | ---------------------- | +| **May 2026** | **Yes** | **`2.14.0`** | + +#### Composition and validation changes + +#### `@interfaceObject` alongside Federation 1 subgraphs + +Previously, composition failed whenever a Federation 2 subgraph used `@interfaceObject` and any Federation 1 subgraph was in the graph. The rule is now scoped to a single type name: composition reports an error only if a Federation 2 subgraph uses `@interfaceObject` on a type `T` and a Federation 1 subgraph defines `@key` on an interface that is also named `T`. `@interfaceObject` on other types can coexist with Federation 1 subgraphs when that specific conflict does not occur. + +#### `@composeDirective` and custom specifications + +When custom directives from the same spec are merged into the supergraph via `@composeDirective`, subgraphs on the latest version of that spec no longer need to each declare every composed directive. A directive definition must appear in at least one of those subgraphs. For example, one subgraph can link a spec, compose both `@foo` and `@bar`, and define both directives, while another subgraph links the same spec, composes only `@foo`, and defines only `@foo`. + +#### `@link` usage + +Composition validates `@link` to prevent name conflicts between linked specs and imported definitions. Disambiguate conflicting names with `import:` (and `as:` when needed). If you linked `https://specs.apollo.dev/tag` or `https://specs.apollo.dev/inaccessible` as separate specs, import `@tag` and `@inaccessible` from the [`federation` specification](/graphos/reference/federation/directives) instead; relying on those standalone links was tied to behavior that this release fixes. + ## v2.13
From e0ca0316014cf45522d88270adcef601c29d9c04 Mon Sep 17 00:00:00 2001 From: dariuszkuc <9501705+dariuszkuc@users.noreply.github.com> Date: Thu, 28 May 2026 11:14:27 -0500 Subject: [PATCH 3/3] fix(composition): pass subgraph name instead of field name to `isMergedDirective` `validateAndFilterExternal` was passing `source.name` (the field name) instead of `this.names[i]` (the subgraph name) to `isMergedDirective`. This caused `shouldComposeDirective` to miss `@composeDirective`-composed directives on external fields, since it looked up the directive under a nonexistent subgraph name. Co-Authored-By: Claude Opus 4.6 --- .changeset/early-cats-impress.md | 11 ++++++ .../compose.composeDirective.test.ts | 36 +++++++++++++++++++ composition-js/src/merging/merge.ts | 2 +- 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 .changeset/early-cats-impress.md diff --git a/.changeset/early-cats-impress.md b/.changeset/early-cats-impress.md new file mode 100644 index 000000000..4be84ecfb --- /dev/null +++ b/.changeset/early-cats-impress.md @@ -0,0 +1,11 @@ +--- +"@apollo/composition": patch +--- + +Fixed `@composeDirective` logic to use correct source for validation + +`validateAndFilterExternal` was passing `source.name` (the field name) +instead of `this.names[i]` (the subgraph name) to `isMergedDirective`. +This caused `shouldComposeDirective` to miss `@composeDirective`-composed +directives on external fields, since it looked up the directive under +a nonexistent subgraph name. \ No newline at end of file diff --git a/composition-js/src/__tests__/compose.composeDirective.test.ts b/composition-js/src/__tests__/compose.composeDirective.test.ts index 1d3a20edc..cad1e8213 100644 --- a/composition-js/src/__tests__/compose.composeDirective.test.ts +++ b/composition-js/src/__tests__/compose.composeDirective.test.ts @@ -1200,4 +1200,40 @@ describe('composing custom core directives', () => { const appliedDirectives = schema.elementByCoordinate('Query.shared')?.appliedDirectives; expect(appliedDirectives?.map(d => [d.name, d.arguments()])).toMatchObject([['auth', { scope: 'VIEWER'}], ['auth', {}]]); }); + + it('rejects composed directive on external field', () => { + const subgraphA = { + typeDefs: gql` + extend schema + @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@shareable"]) + type Query { a: Int } + type Product @key(fields: "id") @shareable { + id: ID! + name: String! + } + `, + name: 'subgraphA', + }; + + const subgraphB = { + typeDefs: gql` + extend schema + @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@external", "@composeDirective", "@requires"]) + @link(url: "https://custom.dev/custom/v1.0", import: ["@custom"]) + @composeDirective(name: "@custom") + directive @custom(scope: String!) on FIELD_DEFINITION | OBJECT + type Product @key(fields: "id") { + id: ID! + name: String! @external @custom(scope: "read") + description: String @requires(fields: "name") @custom(scope: "read") + } + `, + name: 'subgraphB', + }; + + const result = composeServices([subgraphA, subgraphB]); + expect(errors(result)).toStrictEqual([ + ['MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL', '[subgraphB] Cannot apply merged directive @custom(scope: "read") to external field "Product.name"'], + ]); + }); }); diff --git a/composition-js/src/merging/merge.ts b/composition-js/src/merging/merge.ts index 540b7e74b..c8d2b0b7f 100644 --- a/composition-js/src/merging/merge.ts +++ b/composition-js/src/merging/merge.ts @@ -1593,7 +1593,7 @@ class Merger { // Note that if we change our mind on this semantic and wanted directives on external to propagate, then we'll also // need to update the merging of fields since external fields are filtered out (by this very method). for (const directive of source.appliedDirectives) { - if (this.isMergedDirective(source.name, directive)) { + if (this.isMergedDirective(this.names[i], directive)) { // Contrarily to most of the errors during merging that "merge" errors for related elements, we're logging one // error for every application here. But this is because there error is somewhat subgraph specific and is // unlikely to span multiple subgraphs. In fact, we could almost have thrown this error during subgraph validation