# Owner Directive - Schema Proposals

**URL:** <https://community.apollographql.com/t/owner-directive-schema-proposals/8541>\
**Category:** Schema Design\
**Tags:** federation, schema-design\
**Created:** [February 14, 2025, 5:21pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541 "2025-02-14T17:21:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 14, 2025, 5:21pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/1 "2025-02-14T17:21:54Z")

</div>

Hi all, the @owner directive seems like a very useful tool for streamlining the review process and adding the “right” people to review schema changes in a PR, rather than having a long list of gatekeepers.

I’m curious if anyone has implemented something similar for Schema Proposals in Apollo Studio? My organization is looking to leverage this directive in a very similar way to what [these docs](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/entities/enforce-ownership#using-owner-to-determine-required-approvers) say, but instead applying reviewers on a Github PR, applying reviewers on a Schema Proposal.

---

<div class="post-metadata">

**Author:** ![Dan\_Boerner](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/dan_boerner/32/5748_2.png) [@Dan\_Boerner](https://community.apollographql.com/u/Dan_Boerner)\
**Post date:** [February 14, 2025, 10:44pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/2 "2025-02-14T22:44:21Z")

</div>

@greg-apollo gave a great talk on ownership. But not sure if Wayfair ties it to schema proposals. @Serey_Morm ?

> **[Mastering collaboration: How Wayfair built ownership into the Supergraph](https://www.apollographql.com/events/mastering-collaboration-how-wayfair-built-ownership-into-the-supergraph)**
>
> Unlock microservices potential with Apollo GraphQL. Seamlessly integrate APIs, manage data, and enhance performance. Explore Apollo's innovative solutions.

---

<div class="post-metadata">

**Author:** ![shanemyrick](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/shanemyrick/32/5474_2.png) [@shanemyrick](https://community.apollographql.com/u/shanemyrick)\
**Post date:** [February 14, 2025, 11:30pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/3 "2025-02-14T23:30:06Z")

</div>

Using the [GraphOS platform API](https://studio.apollographql.com/public/apollo-platform/variant/main/schema/reference/objects/ProposalMutation?query=reviewer#updateRequestedReviewers) this is possible today that you could script setting the reviewers on a proposal

```graphql
mutation UpdateRequestedReviewers($input: UpdateRequestedReviewersInput!, $name: String!, $graphId: ID!) {
  graph(id: $graphId) {
    variant(name: $name) {
      proposal {
        ... on ProposalMutation {
          updateRequestedReviewers(input: $input) {
            
          }
        }
      }
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![greg-apollo](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/greg-apollo/32/5504_2.png) [@greg-apollo](https://community.apollographql.com/u/greg-apollo)\
**Post date:** [February 15, 2025, 4:10pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/4 "2025-02-15T16:10:33Z")

</div>

While I was still at Wayfair, the plan _was_ to tie it into proposals. Ownership reviews at PR time, while useful, are a little late in the game. I believe it’s best to get the right people involved when designing the API rather than wait until it’s implemented to ask “what do you think?”

What Shane is suggesting was the plan.

- Tag ownership in the schema (so you know who should talk about what)
- [Subscribe](https://www.apollographql.com/docs/graphos/platform/insights/notifications/schema-proposals) to changes to proposals
- Assign reviewers via the GraphOS Platform API based on which subgraph or what schema is changed

You can also enforce your own review limits (say, one reviewer from every changed subgraph has to approve) by subscribing to Proposal changes and the GraphOS Platform API.

---

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 17, 2025, 2:39pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/5 "2025-02-17T14:39:03Z")

</div>

Thank you @greg-apollo & @shanemyrick! I had actually viewed your talk at summit this year, and this was the inspiration behind it all!

I will try this solution out and be sure to share it back with community 🙂

---

<div class="post-metadata">

**Author:** ![shanemyrick](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/shanemyrick/32/5474_2.png) [@shanemyrick](https://community.apollographql.com/u/shanemyrick)\
**Post date:** [February 18, 2025, 5:03pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/6 "2025-02-18T17:03:50Z")

</div>

To help clarify here is a filled out mutation you could make

```graphql
mutation UpdateRequestedReviewers {
  graph(id: "graph id") {
    variant(name: "graph variant aka proposal id") {
      proposal {
        ... on ProposalMutation {
          updateRequestedReviewers(input: {
            reviewerUserIdsToAdd: ["123"]
            reviewerUserIdsToRemove: ["123"]
          }) {
            __typename
            ... on Proposal {
              displayName
              id
              status
            }
            ... on PermissionError {
              message
            }
            ... on Error {
              message
            }
          }
        }
      }
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 18, 2025, 7:14pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/7 "2025-02-18T19:14:03Z")

</div>

I’ve tried making this exact mutation, supplying the proposal ID as the name input field, but it errors out on the variant level, saying it can’t return data for the proposal ID:

```auto
    "message": "Exception while fetching data (/graph/variant) : Variant ddddcb97-c318-45e2-895d-54089b8268f6 not found",
            "path": [
                "graph",
                "variant"
            ],

```

Could I be missing something here?

---

<div class="post-metadata">

**Author:** ![shanemyrick](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/shanemyrick/32/5474_2.png) [@shanemyrick](https://community.apollographql.com/u/shanemyrick)\
**Post date:** [February 18, 2025, 8:03pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/8 "2025-02-18T20:03:07Z")

</div>

The proposal ID is something like `p-1`

---

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 18, 2025, 9:03pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/9 "2025-02-18T21:03:44Z")

</div>

> [@shanemyrick](#):
>
> ```auto
> mutation UpdateRequestedReviewers {
> graph(id: "graph id") {
> variant(name: "graph variant aka proposal id") {
> proposal {
> ... on ProposalMutation {
> updateRequestedReviewers(input: {
> reviewerUserIdsToAdd: ["123"]
> reviewerUserIdsToRemove: ["123"]
> }) {
> __typename
> ... on Proposal {
> displayName
> id
> status
> }
> ... on PermissionError {
> message
> }
> ... on Error {
> message
> }
> }
> }
> }
> }
> }
> }
> 
> ```

I see, that makes sense. I’m now using the correct proposal ID.

Is there any reason this query would fail due to auth? I’m currently providing a Graph Admin API key as the X-API-KEY but getting this error

```auto
  {
      "message": "Exception while fetching data (/_entities[0]/memberships) : NOT_ALLOWED_BY_USER_ROLE",
      "path": [
        "graph",
        "variant",
        "proposal",
        "proposal",
        "backingVariant",
        "graph",
        "account",
        "memberships"
      ],
      "extensions": {
        "serviceName": "identity",
        "code": "DOWNSTREAM_SERVICE_ERROR"
      }
    },

```

---

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 19, 2025, 3:10pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/10 "2025-02-19T15:10:22Z")

</div>

I seemingly can only get this mutation to work if I use my own Personal API key as an org admin.

When using a Graph API Key that has Graph Admin permissions, I get the error above.

This documentation lays out that a Graph Admin or Contributor should have access to update reviewers: [Members, Roles, and Permissions - Apollo GraphQL Docs](https://www.apollographql.com/docs/graphos/platform/access-management/member-roles#schema-proposals-permissions)

This is the level of access my graph has permission for with proposals:

 ![proposal_permissions](https://us1.discourse-cdn.com/flex019/uploads/apollographql/original/2X/d/d7258827a493fc7c76994644edae34c196803657.png)

---

<div class="post-metadata">

**Author:** ![shanemyrick](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/shanemyrick/32/5474_2.png) [@shanemyrick](https://community.apollographql.com/u/shanemyrick)\
**Post date:** [February 19, 2025, 8:59pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/11 "2025-02-19T20:59:16Z")

</div>

@kylekrupp That appears to be a bug with the API keys, can you please raise a support request in the Help Center: [https://support.apollographql.com/](https://support.apollographql.com/)

---

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 19, 2025, 10:14pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/12 "2025-02-19T22:14:08Z")

</div>

Thanks for confirming @shanemyrick , adding the ticket ref here for posterity TSH-18159

---

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 27, 2025, 8:42pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/13 "2025-02-27T20:42:28Z")

</div>

Hey there @greg-apollo / @shanemyrick , I’ve been playing around with the Platform API a bit, but can’t seem to find a way to retrieve the schema diff on a given proposal.

Is there an obvious way to do that I may be missing? Or if not, is there a roundabout way I could programmatically generate the diff that is displayed in the Proposals view?

 ![proposals-diff](https://us1.discourse-cdn.com/flex019/uploads/apollographql/original/2X/8/8b8fb0696884026ecffadafb5254d98a33ddb6d8.png)

---

<div class="post-metadata">

**Author:** ![shanemyrick](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/shanemyrick/32/5474_2.png) [@shanemyrick](https://community.apollographql.com/u/shanemyrick)\
**Post date:** [February 27, 2025, 11:34pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/14 "2025-02-27T23:34:49Z")

</div>

You should be able to find the diff in the `ProposalImplementedChange.diffItem` field: [Studio](https://studio.apollographql.com/public/apollo-platform/variant/main/schema/reference/objects/ProposalImplementedChange?query=Proposal#diffItem)

---

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 28, 2025, 2:23pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/15 "2025-02-28T14:23:49Z")

</div>

Is the only way to retrieve diff data is if the proposal is implemented? My intention is to kick off this automated reviewer requesting when a proposal is opened

---

<div class="post-metadata">

**Author:** ![kylekrupp](https://avatars.discourse-cdn.com/v4/letter/k/7993a0/32.png) [@kylekrupp](https://community.apollographql.com/u/kylekrupp)\
**Post date:** [February 28, 2025, 3:16pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/16 "2025-02-28T15:16:14Z")

</div>

Update: for my intention, I put together this query that allows me to retrieve the core document in the proposal, and the core document of the latest launch for the variant. With this information I could [infer the diff](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/entities/enforce-ownership#using-owner-to-determine-required-approvers) and cherry pick the info I need.

```auto
query Proposal($graphId: ID!, $name: String!) {
  graph(id: $graphId) {
    variant(name: $name) {
      name
      proposal {
        latestRevision {
          launch {
            build {
              result {
                ... on BuildSuccess {
                  coreSchema {
                    coreDocument
                  }
                }
              }
            }
          }
        }
        sourceVariant {
          latestLaunch {
            build {
              result {
                ... on BuildSuccess {
                  coreSchema {
                    coreDocument
                  }
                }
              }
            }
          }
        }
      }
      }
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![shanemyrick](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/shanemyrick/32/5474_2.png) [@shanemyrick](https://community.apollographql.com/u/shanemyrick)\
**Post date:** [February 28, 2025, 8:10pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/17 "2025-02-28T20:10:14Z")

</div>

It looks like you can fetch the structured diff if you have the schema hash of the old schema from the previous version of the proposal to the current

```graphql
query Diff($graphId2: ID!) {
  graph(id: $graphId2) {
    flatDiff(newSdlHash: "", oldSdlHash: "") {
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![vincio\_71](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/vincio_71/32/6008_2.png) [@vincio\_71](https://community.apollographql.com/u/vincio_71)\
**Post date:** [April 21, 2025, 5:03pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/18 "2025-04-21T17:03:11Z")

</div>

Hi everyone, I have an architecture based on NestJS and Apollo Federation with microservices, where each microservice has its own dedicated database and is fully self-contained.  
I spent days trying to find a way to assign an owner to mutations and queries, but without success. Eventually, I found a workaround using the `@tag` directive, since the `@owner` directive is only available for entities.  
This is very limiting because, although the supergraph is a really cool concept, in my case — for permission and group management — it was necessary to define which microservice owned specific queries and mutations.

In general, this kind of “globalization” becomes a limitation in complex systems, unless you switch to an SDL-first architecture, which in my opinion is the wrong approach, as it would mean overriding NestJS and Apollo.

If in the future it became possible to declare the owner of queries and mutations, it would be greatly appreciated.

---

<div class="post-metadata">

**Author:** ![greg-apollo](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/greg-apollo/32/5504_2.png) [@greg-apollo](https://community.apollographql.com/u/greg-apollo)\
**Post date:** [April 21, 2025, 6:39pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/19 "2025-04-21T18:39:25Z")

</div>

I’m not sure I’m following the problem. The `@owner` directive should be a custom directive that you can apply to any schema node you wish (as long as it can accept a directive — so no directive definitions).

Here’s an example `@owner` directive definition:

```graphql
"Defines which graph owns a specific schema node."
directive @owner(
  "The name of the graph that owns the schema node."
  graph: String!
) on ARGUMENT_DEFINITION | ENUM | ENUM_VALUE | FIELD_DEFINITION | INPUT_OBJECT | INPUT_FIELD_DEFINITION | INTERFACE | OBJECT | SCALAR | UNION

```

That example `@owner` directive definition makes it possible to apply the directive to pretty much every schema node in a subgraph (again, excluding directive definitions because they can’t have directives applied to them).

---

<div class="post-metadata">

**Author:** ![vincio\_71](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/vincio_71/32/6008_2.png) [@vincio\_71](https://community.apollographql.com/u/vincio_71)\
**Post date:** [April 21, 2025, 7:06pm UTC](https://community.apollographql.com/t/owner-directive-schema-proposals/8541/20 "2025-04-21T19:06:28Z")

</div>

What I was trying to do is this — inside a resolver of one of my microservices:

```auto
@Query(() => [User], { name: 'findAllUsers' })
@Directive('@owner(name: "users")') // <- here
async findAllUsers(
  @Args('groupId', { type: () => String, nullable: true }) groupId?: string,
): Promise<User[]> {
  return this.usersService.findAllUsers(groupId);
}

```

By adding `@Directive('@owner(name: "users")')`, I was expecting to see something like this in my generated schema:

```auto
type Query {
  findAllUsers(groupId: String): [User!]! @owner(name: "users")
  findOneUser(userId: String!, groupId: String): User! @owner(name: "users")
}

type Mutation {
  createUser(createUserInput: CreateUserInput!): User! @owner(name: "users")
  updateUser(updateUserInput: UpdateUserInput!): User! @owner(name: "users")
  removeUser(userId: String!): DeleteUserOutput! @owner(name: "users")
}

```

But when I try to do this, I get an error like: “did you mean @defer?”

This feature would really help in tracking who the actual owners of specific queries and mutations are — for example, in my case, to define who can execute them based on group membership.

[Next page](https://community.apollographql.com/t/owner-directive-schema-proposals/8541.md?page=2)
