You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Thank you for your interest in contributing! We welcome contributions of all kinds—bug fixes, new features, documentation improvements, and more.
4
4
5
-
**Note:** For MongoDB engineers, please review https://go/ipa-validation-internal-wiki for additional information.
5
+
> **Note:** For MongoDB engineers, please review https://go/ipa-validation-internal-wiki for additional information.
6
6
7
-
## Legacy Spectral Rule Implementation
7
+
---
8
+
## Legacy Spectral Rule Development
8
9
9
10
### Updating the .spectral.yaml Ruleset
10
11
@@ -13,8 +14,8 @@ When adding new rules or updating the `.spectral.yaml` file, the validations wil
13
14
1. Open a pull request (PR) in the `mongodb/openapi` repository with changes to `tools/spectral/.spectral.yaml`.
14
15
2. Ensure that the new Spectral lint checks pass.
15
16
3. Review and merge the PR.
16
-
17
-
## IPA Rule Implementation
17
+
---
18
+
## IPA Rule Development
18
19
19
20
The rule validations are custom JS functions (see [/rulesets/functions](https://github.com/mongodb/openapi/tree/main/tools/spectral/ipa/rulesets/functions)). To learn more about custom functions, refer to the [Spectral Documentation](https://docs.stoplight.io/docs/spectral/a781e290eb9f9-custom-functions).
20
21
@@ -33,7 +34,7 @@ Instead of using the [Spectral overrides approach](https://docs.stoplight.io/doc
33
34
"xgen-IPA-104-resource-has-GET": "Legacy API, not used by infrastructure-as-code tooling",
34
35
}
35
36
```
36
-
37
+
---
37
38
## Testing
38
39
39
40
- IPA Validation related code is tested using [Jest](https://jestjs.io/)
@@ -51,6 +52,7 @@ To run a single test, in this case `singletonHasNoId.test.js`:
51
52
```
52
53
npm run test -- singletonHasNoId
53
54
```
55
+
---
54
56
55
57
## Code Style
56
58
@@ -61,6 +63,7 @@ npx prettier . --write
61
63
```
62
64
63
65
-[ESLint](https://eslint.org/) is being used for linting
66
+
---
64
67
65
68
## Pull Request Checklist
66
69
@@ -73,102 +76,118 @@ npm run gen-ipa-docs
73
76
```
74
77
75
78
-[ ] Reference related issues (e.g., Closes #123)
76
-
77
-
## Technical Decisions
79
+
---
80
+
## Getting Started with IPA Rule Development
78
81
79
82
### Resource & Singleton Evaluation
80
83
81
-
In the IPA Spectral validation, a resource can be identified using a resource collection path.
84
+
In IPA Spectral validation, a **resource** is typically identified using a *resource collection path*, such as `/resource`.
82
85
83
-
For example, resource collection path: `/resource`
86
+
To develop rules that evaluate resource and singleton patterns, you can use the following utility functions:
84
87
85
-
- To get all paths and the path objects for this resource, use [getResourcePathItems](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L143)
88
+
#### Retrieve Resource Path Items
86
89
87
-
- Will return path objects for paths (if present):
88
-
- Resource collection path `/resource`
89
-
- Single resource path `/resource + /{someId}`
90
-
- Custom method path(s)
91
-
-`/resource + /{someId} + :customMethod`
92
-
-`/resource + :customMethod`
90
+
Use [`getResourcePathItems`](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L143) to retrieve all relevant path objects for a given resource:
93
91
94
-
- To check if a resource is a singleton, take the returned object from [getResourcePathItems](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L143) and evaluate the resource using [isSingletonResource](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L71)
95
-
- To check if a path belongs to a resource collection, use [isResourceCollectionIdentifier](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L13)
96
-
- To check if a path belongs to a single resource, use [isSingleResourceIdentifier](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L31)
92
+
- Returns path objects for:
93
+
- Resource collection path: `/resource`
94
+
- Single resource path: `/resource/{someId}`
95
+
- Custom method paths:
96
+
-`/resource/{someId}:customMethod`
97
+
-`/resource:customMethod`
97
98
98
-
 Note: Paths like `/resource/resource` or `/resource/{id}/{id}` are not evaluated as valid resource or single resource paths using isResourceCollectionIdentifier or isSingleResourceIdentifier.
99
+
#### Determine if Resource is a Singleton
99
100
100
-
### Rule Implementation Guidelines
101
+
Use [`isSingletonResource`](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L71) to check if the resource behaves as a singleton. Pass the object returned by `getResourcePathItems`.
101
102
102
-
#### How to Decide when to collect adoption and violation
103
+
#### Identify Resource Collection or Single Resource Paths
103
104
104
-
The collection of adoption, violation, and exemption should be at the same component level - i.e., the same jsonPath level.
105
+
Use the following helpers to check the type of a path:
105
106
106
-
Use
107
+
-[`isResourceCollectionIdentifier`](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L13): Determines if a path represents a resource collection (e.g., `/resource`).
108
+
-[`isSingleResourceIdentifier`](https://github.com/mongodb/openapi/blob/99823b3dfd315f892c5f64f1db50f2124261929c/tools/spectral/ipa/rulesets/functions/utils/resourceEvaluation.js#L31): Determines if a path represents a single resource (e.g., `/resource/{someId}`).
107
109
108
-
-[collectAndReturnViolation(jsonPath, ruleName, errorData)](https://github.com/mongodb/openapi/blob/cd4e085a68cb3bb6078e85dba85ad8ce1674f7da/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js#L14) for violation collection
109
-
-[collectAdoption(jsonPath,ruleName)](https://github.com/mongodb/openapi/blob/cd4e085a68cb3bb6078e85dba85ad8ce1674f7da/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js#L32) for adoption collection
110
-
-[collectException(object, ruleName, jsonPath)](https://github.com/mongodb/openapi/blob/cd4e085a68cb3bb6078e85dba85ad8ce1674f7da/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js#L32) for exception collection
110
+
> **Note:** Paths such as `/resource/resource` or `/resource/{id}/{id}` are not recognized as valid resource or single resource identifiers using `isResourceCollectionIdentifier` or `isSingleResourceIdentifier`.
111
111
112
-
The rule developer should decide on which cases the rule will be considered as adopted and violated.
113
112
114
-
-**Example**: IPA guideline - Enumeration values must be UPPER_SNAKE_CASE
115
-
-**Decision Process**
113
+
### Deciding When to Collect Adoption, Violation, or Exception
116
114
117
-
Custom Spectral rule functions in the format of
115
+
In IPA rule development, **adoption**, **violation**, and **exception** must be collected at the same component level — that is, they must share the same `jsonPath`.
118
116
119
-
```
117
+
#### Helper Functions
118
+
119
+
Use the following helper functions from the `collectionUtils` module:
120
+
121
+
-[`collectAndReturnViolation(jsonPath, ruleName, errorData)`](https://github.com/mongodb/openapi/blob/cd4e085a68cb3bb6078e85dba85ad8ce1674f7da/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js#L14) — for reporting rule violations.
122
+
-[`collectAdoption(jsonPath, ruleName)`](https://github.com/mongodb/openapi/blob/cd4e085a68cb3bb6078e85dba85ad8ce1674f7da/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js#L32) — for marking rule adoption.
123
+
-[`collectException(object, ruleName, jsonPath)`](https://github.com/mongodb/openapi/blob/cd4e085a68cb3bb6078e85dba85ad8ce1674f7da/tools/spectral/ipa/rulesets/functions/utils/collectionUtils.js#L32) — for recording rule exceptions.
124
+
---
125
+
#### Rule Design Guidance
126
+
127
+
As a rule developer, you need to define:
128
+
129
+
- What qualifies as a **violation**?
130
+
- What qualifies as an **adoption**?
131
+
- When should an **exception** be collected?
132
+
---
133
+
#### Custom Rule Function Signature
134
+
135
+
Spectral custom rule functions follow this format:
-`input`: The current component from the OpenAPI spec. Derived from the given and field values in the rule definition.
141
+
-`path`: JSONPath array to the current component.
142
+
-`documentInventory`: The entire OpenAPI specification (use `resolved` or `unresolved` depending on rule context).
122
143
123
-
-`input`: When the Spectral rule is processed according to the given and field parameters of the rule definition, input is the current component being processed.
124
-
-`path`: JSONPath to current input
125
-
-`documentInventory`: Whole OpenAPI spec (retrieve resolved or unresolved according to the need)
144
+
---
126
145
127
-
When implementing a custom Spectral rule, please follow these conventions:
128
-
129
-
- If adoption, violation, and exception data should be collected at the same component level, ensure all helper functions use the same `jsonPath`.
130
-
This path is either passed directly as the Spectral rule function's parameter or derived from it.
131
-
- Use this `jsonPath` consistently in:
146
+
#### Rule Implementation Conventions
132
147
148
+
- Use the **same `jsonPath`** for:
133
149
-`collectAndReturnViolation`
134
150
-`collectAdoption`
135
151
-`collectException`
136
152
137
-
- Input assumptions:
138
-
The custom rule function assumes its input is never undefined. You do not need to validate the presence or structure of the input parameter.
153
+
> 💡 This path should either be the `path` parameter from the rule function or a derived value from it.
139
154
140
-
- Expected behavior: A rule must collect exactly one of:
155
+
- A rule must collect **only one** of the following for each evaluation:
156
+
- An **adoption**
157
+
- A **violation**
158
+
- An **exception**
141
159
142
-
- an adoption,
143
-
-a violation, or
144
-
-an exception.
160
+
- You can include **multiple error messages** for a violation. To do so:
161
+
-Gather the messages into an array
162
+
-Pass them to `collectAndReturnViolation`
145
163
146
-
- Violations can include multiple error messages, if needed.
147
-
In that case, gather all messages into an array and pass it to `collectAndReturnViolation`, which is responsible for displaying messages to users.
164
+
- The `input` parameter is assumed to be **defined** when the rule runs. No need to check for its existence.
148
165
149
-
💡 Example:
166
+
---
150
167
151
-
If you're validating an `enum` and want to highlight each invalid value, collect the individual error messages into an array and pass it to `collectAndReturnViolation`.
168
+
#### Example: Enum Case Validation
169
+
To validate an enum and show a separate error for each invalid value:
####How to Decide the component level at which the rule will be processed
190
+
### How to Decide the component level at which the rule will be processed
172
191
173
192
When designing a rule, think from the custom rule function’s perspective.
174
193
Consider which `input` and `jsonPath` values will be most helpful for accurately evaluating the rule and collecting adoption, violation, or exception data.
@@ -246,3 +265,31 @@ then:
246
265
field: @key
247
266
function: "customRuleFunction"
248
267
```
268
+
269
+
**Case 3**: Parameterized rules
270
+
271
+
The `functionOptions` in the rule definition can be used to pass additional parameters to your custom rule function. This is useful when you need to configure or provide specific settings to the rule function for more flexible behavior.
272
+
273
+
-**Example**: Define `functionOptions` within the rule to adjust behavior:
0 commit comments