-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgraphql.yaml
More file actions
214 lines (182 loc) · 8.96 KB
/
graphql.yaml
File metadata and controls
214 lines (182 loc) · 8.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# GraphQL API Code Review Guidelines
# Comprehensive rules for schema design, security, performance, error handling, and best practices
description: "Code review guidelines for GraphQL API design covering schema, security, performance, and best practices"
globs:
- "**/*.graphql"
- "**/*.gql"
- "**/*resolver*"
- "**/*schema*"
- "**/*typeDef*"
- "**/*graphql*"
- "**/*.ts"
- "**/*.js"
- "**/*.py"
- "**/*.java"
- "**/*.go"
- "**/*.rb"
rules:
# ============================================================================
# SCHEMA DESIGN RULES
# ============================================================================
- name: use-consistent-naming-conventions
description: >
Use PascalCase for types (User, OrderItem), camelCase for fields (firstName,
createdAt) and arguments. Use SCREAMING_SNAKE_CASE for enum values. Maintain
consistency across the entire schema.
severity: medium
- name: design-nullable-fields-intentionally
description: >
Be intentional about nullability. Non-null (!) should be default for fields
that always have values. Allow null for optional fields, fields that may fail
independently, or list items. Over-using non-null can cause entire query failures.
severity: high
- name: use-deprecation-properly
description: >
Use @deprecated directive with reason when removing fields. Provide migration
path in deprecation reason. Monitor usage before removal. Never remove fields
without deprecation period. Example: @deprecated(reason: "Use newField instead")
severity: high
- name: design-relay-compliant-connections
description: >
Use Relay connection specification for paginated lists (edges, nodes, pageInfo,
cursor-based pagination). This provides consistent pagination patterns and
enables efficient cursor-based fetching across the API.
severity: medium
- name: avoid-deeply-nested-types
description: >
Limit type nesting depth. Deep nesting indicates potential N+1 problems and
complexity. Consider flattening or using interfaces. Deeply nested queries
are hard to optimize and can cause performance issues.
severity: medium
# ============================================================================
# SECURITY RULES
# ============================================================================
- name: implement-query-depth-limiting
description: >
Limit query depth to prevent malicious deeply nested queries that exhaust
server resources. Typical limit is 10-15 levels. Return error for queries
exceeding depth limit. Configure based on your schema structure.
severity: critical
- name: implement-query-complexity-analysis
description: >
Calculate and limit query complexity based on requested fields, connections,
and arguments. Assign costs to fields (especially lists and computed fields).
Reject queries exceeding complexity threshold. Consider rate limiting by complexity.
severity: high
- name: disable-introspection-in-production
description: >
Disable GraphQL introspection in production to prevent schema enumeration.
Attackers can use introspection to discover your entire API surface. Enable
introspection only in development and staging environments.
severity: high
- name: implement-field-level-authorization
description: >
Implement authorization at the field level, not just query level. Sensitive
fields should check permissions in resolvers. Use directives like @auth for
declarative authorization. Don't expose data users shouldn't access.
severity: critical
- name: prevent-batch-attacks
description: >
Limit the number of operations in a single request (query batching). Attackers
can send thousands of queries in one request. Implement operation count limits
and rate limiting per operation.
severity: high
# ============================================================================
# PERFORMANCE RULES
# ============================================================================
- name: use-dataloader-for-batching
description: >
Use DataLoader or equivalent to batch and cache database/API calls within
a request. This solves the N+1 query problem where fetching a list triggers
individual fetches for each item. Essential for nested relationship queries.
severity: critical
- name: implement-query-result-caching
description: >
Cache query results at appropriate levels (CDN, application, resolver).
Use persisted queries for caching by query hash. Consider response caching
headers. Cache invalidation should match data update patterns.
severity: medium
- name: optimize-resolver-execution
description: >
Resolvers should be efficient and avoid redundant work. Use lazy loading
for expensive fields. Consider field-level caching. Profile resolver
performance and optimize hot paths.
severity: medium
- name: use-persisted-queries
description: >
Use persisted/stored queries to reduce request size and enable caching.
Clients send query ID instead of full query text. This also provides
security by only allowing pre-approved queries in production.
severity: medium
- name: implement-proper-pagination
description: >
Always paginate list fields. Use cursor-based pagination for real-time data
or large datasets. Include reasonable default and maximum limits. Never
return unbounded lists that could return millions of records.
severity: high
# ============================================================================
# ERROR HANDLING RULES
# ============================================================================
- name: use-consistent-error-format
description: >
Use consistent error structure following GraphQL spec. Include meaningful
error messages, error codes, and paths. Structure: {"message": "...",
"extensions": {"code": "...", "field": "..."}}. Document error codes.
severity: high
- name: handle-partial-responses
description: >
GraphQL can return partial data with errors. Handle null fields gracefully
in resolvers. Use error boundaries to prevent single field failure from
failing entire query. Return data where possible, errors where failed.
severity: medium
- name: provide-validation-error-details
description: >
Return detailed validation errors with field paths and constraint violated.
Use extensions for structured error data. Example: {"extensions": {"code":
"VALIDATION_ERROR", "field": "email", "constraint": "format"}}.
severity: medium
- name: mask-internal-errors
description: >
Never expose internal error details, stack traces, or database errors to
clients. Log detailed errors server-side, return sanitized messages to
clients. In production, use generic messages for unexpected errors.
severity: high
# ============================================================================
# BEST PRACTICES RULES
# ============================================================================
- name: use-input-types-for-mutations
description: >
Use input types for mutation arguments instead of multiple scalar arguments.
This improves readability and allows evolution. Example: createUser(input:
CreateUserInput!) instead of createUser(name: String!, email: String!).
severity: medium
- name: design-mutations-for-specific-actions
description: >
Design mutations for specific actions rather than generic CRUD. Use action-
oriented names (publishPost, cancelOrder) that reflect business operations.
This provides better semantics and allows for proper validation.
severity: medium
- name: use-custom-scalars-appropriately
description: >
Define custom scalars for domain-specific types (DateTime, Email, URL, UUID).
Implement proper serialization, parsing, and validation. Custom scalars
provide type safety and consistent handling across the schema.
severity: low
- name: prefer-interfaces-for-shared-fields
description: >
Use interfaces for types sharing common fields (Node interface with id).
Use unions for types without shared fields. Interfaces enable polymorphic
queries and consistent field access across types.
severity: medium
- name: document-schema-thoroughly
description: >
Add descriptions to all types, fields, arguments, and enum values. Use
multi-line strings for detailed documentation. Descriptions appear in
GraphQL IDE tools and generated documentation.
severity: medium
- name: version-schema-changes-carefully
description: >
GraphQL APIs are typically versionless. Add fields freely, deprecate before
removing. Track schema changes in version control. Use schema diffing tools
to detect breaking changes. Monitor field usage before deprecation.
severity: high