Skip to content

Commit c969ba3

Browse files
authored
Fully Qualified Operation Name (FQON) (#7)
Introduces **GAP-7: Fully Qualified Operation Names (FQON)** — a human-readable, unambiguous identifier for GraphQL operations that can be used as lookup keys in static configuration files without coupling to document IDs. Previously discussed: graphql/graphql-spec#1185
2 parents 858a76a + a1e6ed7 commit c969ba3

3 files changed

Lines changed: 233 additions & 0 deletions

File tree

gaps/GAP-7/DRAFT.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Fully Qualified Operation Name (FQON)
2+
3+
**Introduction**
4+
5+
:: This document specifies _Fully Qualified Operation Name_ (FQON), a
6+
human‑readable, unambiguous identifier for GraphQL operations.
7+
8+
The primary motivation is to define a "lookup key" that may be used in static
9+
configuration files (e.g. for alerting rules per operation) which correctly
10+
targets operations, but without having to update the configuration each time a
11+
_document id_ changes.
12+
13+
This specification assumes usage of
14+
[trusted documents](https://graphql.org/learn/security/#trusted-documents) and
15+
[Git version control](https://git-scm.com/).
16+
17+
**Example**
18+
19+
Given the following operation defined in a Git repository named `yelp/frontend`,
20+
and in a package named `styleguide`:
21+
22+
```graphql example
23+
query GetHeaderData {
24+
...
25+
}
26+
```
27+
28+
The _FQON_ for this operation may be defined as:
29+
30+
```example
31+
GetHeaderData:styleguide:yelp/frontend:1
32+
```
33+
34+
When defining alerting rules for this operation, we can target all versions of
35+
this operation by omitting the _version_ suffix:
36+
37+
```example
38+
GetHeaderData:styleguide:yelp/frontend
39+
```
40+
41+
**Motivation**
42+
43+
We may identify operations using either:
44+
45+
- The _operation name_ (e.g. {"GetHeaderData"})
46+
- The _document id_ produced by hashing the operation body (e.g. {"605fad0ee0a88..."})
47+
48+
Because GraphQL operation names are not be guaranteed to be globally unique,
49+
they cannot reliably identify an operation across multiple platforms or
50+
deployment versions. On the other hand, a _document id_ is guaranteed to be
51+
unique but is inconvenient for humans to read and maintain.
52+
53+
Note: See <README.md> for additional context.
54+
55+
**Use Cases**
56+
57+
- A _FQON_ may be printed instead of the operation name in application logs.
58+
This encourages correct behavior when humans use this identifier to look up
59+
the operation body in the document registry or codebase.
60+
- A partial _FQON_ may be used instead of a _document id_ as lookup keys in
61+
static configuration files (e.g. alerting rules) in order to avoid duplication
62+
and extra steps when an operation is updated (and thus, its _document id_).
63+
64+
## Definition
65+
66+
FullyQualifiedOperationName :: OperationName : Project? : RepoFullName : Version
67+
68+
OperationName
69+
: The _Name_ of the operation as declared on the _OperationDefinition_ node.
70+
71+
Project
72+
: The identifier for the package or directory containing the operation.
73+
: This is defined only for operations that live in a monorepo.
74+
75+
RepoFullName
76+
: The full name of the Git repository (in the format of {"owner/repo"}).
77+
78+
Version
79+
: A positive integer that increments each time the document body changes.
80+
: The tuple of _OperationName_, _Project_ and _RepoFullName_ identifies a
81+
document; the _Version_ part distinguishes its revisions.
82+
: The _trusted document_ registry or other persistence layer must calculate or
83+
store version numbers, starting at {1} and increasing monotonically.
84+
85+
**Examples**
86+
87+
A _Fully Qualified Operation Name_ with all parts:
88+
89+
```example
90+
GetHeaderData:styleguide:yelp/frontend:1
91+
```
92+
93+
A _Fully Qualified Operation Name_ which omits `Project` (i.e.
94+
`petstore/website` is _not_ a monorepo, and has no concept of "projects"):
95+
96+
```example
97+
AllPets::petstore/website:1
98+
```
99+
100+
## Partial Matches
101+
102+
Any _FQON_ part may be omitted to perform a partial match.
103+
104+
With the exception of omitting _Project_, partial matches must also omit the
105+
`:Version` suffix.
106+
107+
The primary use case of this specification is to omit `:Version` for use as
108+
lookup keys in static configuration files, as a way to target to all versions
109+
of an operation.
110+
111+
**Examples**
112+
113+
| Pattern | Matches |
114+
| --------------------------- | ------------------------------------------------------------------------------------------------------- |
115+
| `GetFoo::` | All operations named {"GetFoo"} |
116+
| `::bazcorp/qux` | All operations inside the {"bazcorp/qux"} Git repository |
117+
| `GetFoo:barpkg:bazcorp/qux` | All operations named {"GetFoo"} inside the {"barpkg"} package inside the {"bazcorp/qux"} Git repository |
118+
119+
## Security Considerations
120+
121+
It is recommended to avoid exposing FQONs in client code to avoid leaking
122+
potentially sensitive internal repository names or project/directory names.
123+
124+
Clients should still send only the _document id_ over the wire, which is opaque.

gaps/GAP-7/README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# GAP-7: Fully Qualified Operation Name (FQON)
2+
3+
Fully Qualified Operation Names (FQONs) are an alternate way to identify and
4+
refer to GraphQL operations that provide both human readability and uniqueness
5+
guarantees.
6+
7+
The primary motivation is to define a "lookup key" that may be used in static
8+
configuration files (e.g. for alerting rules per operation) which correctly
9+
targets operations, but without having to update the configuration each time a
10+
_document id_ changes.
11+
12+
## The problem
13+
14+
When using
15+
[trusted documents](https://graphql.org/learn/security/#trusted-documents), we
16+
may identify operations in two different ways:
17+
18+
1. The "operation name" (e.g. `GetConsumerHeaderData`)
19+
2. The "document id" (e.g. `605fad0ee0a88...`)
20+
21+
_Operation names are not guaranteed to be unique_.
22+
23+
When using operation names, a developer might see `"GetUserInfo"` in service log,
24+
copy and paste that string, use `git grep` and find it in the codebase -- only
25+
to later discover it's the _wrong_ `GetUserInfo` query!
26+
27+
- Query names are only guaranteed to be unique with additional tooling.
28+
- Even if tooling guarantees uniqueness within a repository, query names could
29+
be reused in a _different_ repository — e.g. Web/iOS/Android code might
30+
feasibly live in different Git repositories, and reuse operation names for
31+
similar features.
32+
- Additionally, servers may receive traffic for different versions of
33+
the same query in order to support old mobile application installs - which
34+
would share the same operation name.
35+
36+
Document IDs are unambiguous and may be used to solve this problem. However,
37+
document IDs are not human friendly since they don't carry any semantic meaning,
38+
which encourages developers to use document names in instead - which leads the
39+
footgun outlined above.
40+
41+
Additionally, by definition, document IDs change each time the operation is
42+
updated. If we use document IDs as lookup keys in an alerting configuration
43+
file, this must be updated each time a new version of the query is published.
44+
This creates duplication and a maintenance burden.
45+
46+
## Solution
47+
48+
A _Fully Qualified Operation Name_ (FQON) is a human readable string that can
49+
provide the same guarantees of uniqueness as document IDs, but and can be used
50+
partially to omit the version number in such cases as alert config files.
51+
52+
**Example**:
53+
54+
```yaml
55+
# alert_thresholds.yaml
56+
operations:
57+
- fqon: GetFoo::bazcorp/qux
58+
error_ratio: 0.3
59+
owner: myteam@example.com
60+
- fqon: BarStuff::bazcorp/qux
61+
error_ratio: 0.4
62+
alert: myteam@example.com
63+
```
64+
65+
## Definition
66+
67+
The format is:
68+
69+
```
70+
name:project:repo:version
71+
```
72+
73+
This is enough information to unambiguously identify the exact document
74+
(assuming that client tooling guarantees no duplicate operation names per
75+
project).
76+
77+
**Example**:
78+
79+
```
80+
GetConsumerHeaderData:yelp-styleguide:yelp/frontend:3
81+
```
82+
83+
The right hand side components of the FQON can be omitted for a partial match:
84+
85+
**Example**:
86+
87+
```
88+
GetConsumerHeaderData:yelp-styleguide:yelp/frontend
89+
```
90+
91+
^ this will match any version of the "same" query, and is recommended for use
92+
as lookup keys in static configuration files
93+
94+
### ARN Syntax
95+
96+
`:` as a separator is inspired by [ARNs](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html)

gaps/GAP-7/metadata.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
id: 7
2+
title: "Fully Qualified Operation Names"
3+
summary: >
4+
A human-readable, unambiguous identifier for GraphQL operations. May be used
5+
as lookup keys in static configuration files as an alternative to persisted
6+
document IDs.
7+
status: proposal
8+
authors:
9+
- name: "Mark Larah"
10+
email: "markl@yelp.com"
11+
githubUsername: "@magicmark"
12+
sponsor: "@magicmark"
13+
discussion: "https://github.com/graphql/gaps/pull/7"

0 commit comments

Comments
 (0)