Repository: stoplightio/spectral (ts)

Issue:
Unrecommend openapi-tags
**User story.**
As a non-Stoplight user I do not understand the importance of tags, so it is a surprise when im told I absolutely must add them.

**Is your feature request related to a problem?**
Spectral users occasionally ask why Spectral is telling them to do things not in the OpenAPI spec. The answer is usually "this is a linter, not a validator" and that most of the rules are useful: avoiding bugs, stopping them getting hacked, etc. 

One rule which doesn't fit the description is `openapi-tags`. It _is_ useful for bigger APIs, but I'm working on a single endpoint OpenAPI description and adding tags to that is pretty redundant. It's there because Stoplight docs like tags, but for a single endpoint API I don't need my docs grouped like that anyhow.

**Describe the solution you'd like**

For v6.0 we should just make this one rule `recommended: false`.

**Additional context**

_In the future I'd like to look into a `spectral-stoplight-ruleset` with all sorts of rules relevant to Stoplight but not particularly relevant to other tools. Food for thought whilst working on this so we know the direction at least._
`operation-2xx-response` rule should not be recommended
I suggest to move `operation-2xx-response` rule out from recommended, as it is reasonable to have endpoints that have no success response but only 3xx redirects. Or maybe change the rule to allow 2xx or 3xx responses.

What do you think?

Pull request description:
feat: removing some rules people dont like
Fixes #1273
Fixes #1132

**Checklist**

- [x] Tests added / updated
- [x] Docs added / updated

**Does this PR introduce a breaking change?**

- [x] Yes
- [ ] No

We're preparing for v6.0, which will include some major and excellent changes, but also some breaking changes to the bundled OpenAPI ruleset. These rules come from a bunch of feedback from the community about which rules should be showing up by default, and which are useful for "strict mode" (running with `extends: [[spectral:oas, all]]`. 

If you want any of these rules to stick around, speak now or forever hold your peace! 

**TLDR**

1. Bumping openapi-tag out to `recommended: false`(loads of people don't use tags and Studio doesn't help enough to make this easy for people who dont know what they are anyway). #1132
1. Changed operation-2xx-response to operation-success-response to solve #1273.
1. Removing operation-default-response altogether.

Patch:
diff --git a/.nvmrc b/.nvmrc
index 73bffb03..0aee7e7e 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1,1 +1,1 @@
-10.17.0
+12.8.0
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2c0cd070..e6815ba7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,7 +17,7 @@ Our Code of Conduct exists because of that dedication, and we do not tolerate ha
 Yarn is a package manager for your code, similar to npm. While you can use npm to use Spectral in your own project, we use yarn for development of Spectral.
 
 1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your computer.
-2. Install yarn: Refer to the [installation documentation](https://classic.yarnpkg.com/en/docs/install/) according to your developement operating system
+2. Install yarn: Refer to the [installation documentation](https://classic.yarnpkg.com/en/docs/install/) according to your development operating system
 3. In your terminal, navigate to the directory you cloned Spectral into (check that you are on the `develop` branch).
 4. Install the dependencies: `yarn`
 5. Build Spectral: `yarn build`
diff --git a/README.md b/README.md
index 5250bcef..4ed51232 100644
--- a/README.md
+++ b/README.md
@@ -39,19 +39,19 @@ This package is [Treeware](https://treeware.earth) so if you would like to thank
 
 ## Documentation
 
-Take a look at our [getting started documentation](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/getting-started/1-concepts.md), then peek through some of our guides:
+Take a look at our [getting started documentation](https://meta.stoplight.io/docs/spectral/docs/getting-started/concepts.md), then peek through some of our guides:
 
-- [Different Workflows](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/guides/1-workflows.md) - When and where should you use Spectral? Editors, Git-hooks, Continuous Integration, GitHub Actions, wherever you like!
-- [Using the command-line interface](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/guides/2-cli.md) - Quickest way to get going with Spectral is in the CLI.
-- [Using the JavaScript API](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/guides/3-javascript.md) - Access the _raw power_ of Spectral via the JS, or hey, TypeScript if you want.
-- [Custom Rulesets](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/guides/4-custom-rulesets.md) - Don't like our rules? Throw em out and make your own.
-- [Custom Functions](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/guides/5-custom-functions.md) - Rules can do absolutely anything, just write a little code.
+- [Different Workflows](https://meta.stoplight.io/docs/spectral/docs/guides/1-workflows.md) - When and where should you use Spectral? Editors, Git-hooks, Continuous Integration, GitHub Actions, wherever you like!
+- [Using the command-line interface](https://meta.stoplight.io/docs/spectral/docs/guides/2-cli.md) - Quickest way to get going with Spectral is in the CLI.
+- [Using the JavaScript API](https://meta.stoplight.io/docs/spectral/docs/guides/3-javascript.md) - Access the _raw power_ of Spectral via the JS, or hey, TypeScript if you want.
+- [Custom Rulesets](https://meta.stoplight.io/docs/spectral/docs/guides/4-custom-rulesets.md) - Don't like our rules? Throw em out and make your own.
+- [Custom Functions](https://meta.stoplight.io/docs/spectral/docs/guides/5-custom-functions.md) - Rules can do absolutely anything, just write a little code.
 
 ## FAQs
 
 ### How is this different to AJV
 
-[Ajv](https://www.npmjs.com/package/ajv) is a JSON Schema validator, and Spectral is a JSON/YAML linter. Instead of just validating against JSON Schema, it can be used to write rules for any sort of JSON/YAML object, which could be JSON Schema, or OpenAPI, or anything similar. Spectral does expose a [`schema` function](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/reference/functions.md) that you can use in your rules to validate all or part of the target object with JSON Schema (we even use Ajv used under the hood for this), but that's just one of many functions.
+[Ajv](https://www.npmjs.com/package/ajv) is a JSON Schema validator, and Spectral is a JSON/YAML linter. Instead of just validating against JSON Schema, it can be used to write rules for any sort of JSON/YAML object, which could be JSON Schema, or OpenAPI, or anything similar. Spectral does expose a [`schema` function](https://meta.stoplight.io/docs/spectral/docs/reference/functions.md) that you can use in your rules to validate all or part of the target object with JSON Schema (we even use Ajv used under the hood for this), but that's just one of many functions.
 
 ### I want to lint my OpenAPI documents but don't want to implement Spectral right now.
 
diff --git a/docs/guides/4-custom-rulesets.md b/docs/guides/4-custom-rulesets.md
index 3f03776d..63a38230 100644
--- a/docs/guides/4-custom-rulesets.md
+++ b/docs/guides/4-custom-rulesets.md
@@ -107,12 +107,12 @@ If you're just looking change the severity of the rule, there is a handy shortcu
 
 ## Changing Rule Severity
 
-Maybe you want to use the rules from the `spectral:oas` ruleset, but instead of `operation-2xx-response` triggering an error you'd like it to trigger a warning instead.
+Maybe you want to use the rules from the `spectral:oas` ruleset, but instead of `operation-success-response` triggering an error you'd like it to trigger a warning instead.
 
 ```yaml
 extends: spectral:oas
 rules:
-  operation-2xx-response: warn
+  operation-success-response: warn
 ```
 
 Available severity levels are `error`, `warn`, `info`, `hint`, and `off`.
diff --git a/docs/reference/openapi-rules.md b/docs/reference/openapi-rules.md
index bc7aeb6b..38e408ee 100644
--- a/docs/reference/openapi-rules.md
+++ b/docs/reference/openapi-rules.md
@@ -8,9 +8,9 @@ In your ruleset file you can add `extends: "spectral:oas"` and you'll get all of
 
 These rules apply to both OpenAPI v2 and v3.
 
-### operation-2xx-response
+### operation-success-response
 
-Operation must have at least one `2xx` response. Any API operation (endpoint) can fail but presumably it is also meant to do something constructive at some point. If you forget to write out a success case for this API, then this rule will let you know.
+Operation must have at least one `2xx` or `3xx` response. Any API operation (endpoint) can fail, but presumably it is also meant to do something constructive at some point. If you forget to write out a success case for this API, then this rule will let you know.
 
 **Recommended:** Yes
 
@@ -253,10 +253,6 @@ Why? Well, you _can_ reference tags arbitrarily in operations, and definition is
 
 Defining tags allows you to add more information like a `description`. For more information see [tag-description](#tag-description).
 
-**Recommended:** Yes
-
-### operation-default-response
-
 **Recommended:** No
 
 ### operation-description
@@ -292,17 +288,6 @@ Use just one tag for an operation, which is helpful for some documentation syste
 
 **Recommended:** No
 
-### operation-summary-formatted
-
-<!-- theme: warning -->
-> ### Removed in v5.0
->
-> This rule was removed in Spectral v5.0, so if you are relying on it you can find the [old definition here](https://github.com/stoplightio/spectral/blob/v4.2.0/src/rulesets/oas/index.json#L312) and paste it into your [custom ruleset](../getting-started/3-rulesets.md).
-
-Operation `summary` should start with upper case and end with a dot.
-
-**Recommended:** No
-
 ### operation-tags
 
 Operation should have non-empty `tags` array.
diff --git a/src/rulesets/oas/functions/oasOp2xxResponse.ts b/src/rulesets/oas/functions/oasOpSuccessResponse.ts
similarity index 59%
rename from src/rulesets/oas/functions/oasOp2xxResponse.ts
rename to src/rulesets/oas/functions/oasOpSuccessResponse.ts
index 0fbbd098..0b91322e 100644
--- a/src/rulesets/oas/functions/oasOp2xxResponse.ts
+++ b/src/rulesets/oas/functions/oasOpSuccessResponse.ts
@@ -1,18 +1,18 @@
 import type { IFunction, IFunctionResult } from '../../../types';
 
-export const oasOp2xxResponse: IFunction = targetVal => {
+export const oasOpSuccessResponse: IFunction = targetVal => {
   if (!targetVal) {
     return;
   }
 
   const results: IFunctionResult[] = [];
   const responses = Object.keys(targetVal);
-  if (responses.filter(response => Number(response) >= 200 && Number(response) < 300).length === 0) {
+  if (responses.filter(response => Number(response) >= 200 && Number(response) < 400).length === 0) {
     results.push({
-      message: 'operations must define at least one 2xx response',
+      message: 'operations must define at least one 2xx or 3xx response',
     });
   }
   return results;
 };
 
-export default oasOp2xxResponse;
+export default oasOpSuccessResponse;
diff --git a/src/rulesets/oas/index.json b/src/rulesets/oas/index.json
index 17c07877..abab8cc9 100644
--- a/src/rulesets/oas/index.json
+++ b/src/rulesets/oas/index.json
@@ -3,7 +3,7 @@
   "formats": ["oas2", "oas3"],
   "functions": [
     "oasDocumentSchema",
-    "oasOp2xxResponse",
+    "oasOpSuccessResponse",
     "oasOpFormDataConsumeCheck",
     "oasOpIdUnique",
     "oasOpParams",
@@ -14,14 +14,14 @@
     "refSiblings"
   ],
   "rules": {
-    "operation-2xx-response": {
-      "description": "Operation must have at least one `2xx` response.",
+    "operation-success-response": {
+      "description": "Operation must have at least one `2xx` or `3xx` response.",
       "recommended": true,
       "type": "style",
       "given": "$.paths.*[?( @property === 'get' || @property === 'put' || @property === 'post' || @property === 'delete' || @property === 'options' || @property === 'head' || @property === 'patch' || @property === 'trace' )]",
       "then": {
         "field": "responses",
-        "function": "oasOp2xxResponse"
+        "function": "oasOpSuccessResponse"
       }
     },
     "oas2-operation-formData-consume-check": {
@@ -173,7 +173,7 @@
     },
     "openapi-tags": {
       "description": "OpenAPI object should have non-empty `tags` array.",
-      "recommended": true,
+      "recommended": false,
       "type": "style",
       "given": "$",
       "then": {
@@ -187,16 +187,6 @@
         }
       }
     },
-    "operation-default-response": {
-      "description": "Operations must have a default response.",
-      "recommended": false,
-      "type": "style",
-      "given": "$.paths.*.*.responses",
-      "then": {
-        "field": "default",
-        "function": "truthy"
-      }
-    },
     "operation-description": {
       "description": "Operation `description` must be present and non-empty string.",
       "recommended": true,


Test patch:
diff --git a/src/__tests__/__fixtures__/bare-oas-ruleset.json b/src/__tests__/__fixtures__/bare-oas-ruleset.json
index a4983421..bd98dc4a 100644
--- a/src/__tests__/__fixtures__/bare-oas-ruleset.json
+++ b/src/__tests__/__fixtures__/bare-oas-ruleset.json
@@ -17,8 +17,8 @@
   "except": {
     "/test/file.json#/info": ["info-contact", "info-description"],
     "/test/file.json#": [ "oas3-api-servers"],
-    "/test/file.json#/paths/~1a.two/get": ["operation-2xx-response"],
-    "/test/file.json#/paths/~1b.three/get": ["operation-2xx-response"],
+    "/test/file.json#/paths/~1a.two/get": ["operation-success-response"],
+    "/test/file.json#/paths/~1b.three/get": ["operation-success-response"],
     "another.yaml#": ["dummy-rule", "info-contact"]
   }
 }
diff --git a/src/__tests__/__fixtures__/custom-oas-ruleset.json b/src/__tests__/__fixtures__/custom-oas-ruleset.json
index ef243bcf..311bc870 100644
--- a/src/__tests__/__fixtures__/custom-oas-ruleset.json
+++ b/src/__tests__/__fixtures__/custom-oas-ruleset.json
@@ -18,8 +18,8 @@
   "except": {
     "/test/file.json#/info": ["info-contact", "info-description"],
     "/test/file.json#": [ "oas3-api-servers"],
-    "/test/file.json#/paths/~1a.two/get": ["operation-2xx-response"],
-    "/test/file.json#/paths/~1b.three/get": ["operation-2xx-response"],
+    "/test/file.json#/paths/~1a.two/get": ["operation-success-response"],
+    "/test/file.json#/paths/~1b.three/get": ["operation-success-response"],
     "another.yaml#": ["dummy-rule", "info-contact"]
   }
 }
diff --git a/src/__tests__/linter.jest.test.ts b/src/__tests__/linter.jest.test.ts
index 7885033c..49548a50 100644
--- a/src/__tests__/linter.jest.test.ts
+++ b/src/__tests__/linter.jest.test.ts
@@ -620,26 +620,26 @@ console.log(this.cache.get('test') || this.cache.set('test', []).get('test'));
       expect(res).toEqual(
         expect.arrayContaining([
           expect.objectContaining({
-            code: 'operation-2xx-response',
-            message: 'Operation must have at least one `2xx` response.',
+            code: 'operation-success-response',
+            message: 'Operation must have at least one `2xx` or `3xx` response.',
             path: ['paths', '/a.one', 'get'],
             source: '/test/file.json',
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
-            message: 'Operation must have at least one `2xx` response.',
+            code: 'operation-success-response',
+            message: 'Operation must have at least one `2xx` or `3xx` response.',
             path: ['paths', '/a.three', 'get'],
             source: '/test/file.json',
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
-            message: 'Operation must have at least one `2xx` response.',
+            code: 'operation-success-response',
+            message: 'Operation must have at least one `2xx` or `3xx` response.',
             path: ['paths', '/b.one', 'get'],
             source: '/test/file.json',
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
-            message: 'Operation must have at least one `2xx` response.',
+            code: 'operation-success-response',
+            message: 'Operation must have at least one `2xx` or `3xx` response.',
             path: ['paths', '/b.two', 'get'],
             source: '/test/file.json',
           }),
@@ -649,8 +649,8 @@ console.log(this.cache.get('test') || this.cache.set('test', []).get('test'));
       expect(res).toEqual(
         expect.not.arrayContaining([
           expect.objectContaining({
-            code: 'operation-2xx-response',
-            message: 'Operation must have at least one `2xx` response.',
+            code: 'operation-success-response',
+            message: 'Operation must have at least one `2xx` or `3xx` response.',
             path: ['paths', '/a.two', 'get'],
             source: '/test/file.json',
           }),
@@ -660,8 +660,8 @@ console.log(this.cache.get('test') || this.cache.set('test', []).get('test'));
       expect(res).toEqual(
         expect.not.arrayContaining([
           expect.objectContaining({
-            code: 'operation-2xx-response',
-            message: 'Operation must have at least one `2xx` response.',
+            code: 'operation-success-response',
+            message: 'Operation must have at least one `2xx` or `3xx` response.',
             path: ['paths', '/b.three', 'get'],
             source: '/test/file.json',
           }),
diff --git a/src/__tests__/linter.test.ts b/src/__tests__/linter.test.ts
index 66ec4bd2..caa21a39 100644
--- a/src/__tests__/linter.test.ts
+++ b/src/__tests__/linter.test.ts
@@ -193,13 +193,13 @@ describe('linter', () => {
     spectral.setRules({
       ...mergeRules(oasRules, {
         'oas3-valid-schema-example': 'off',
-        'operation-2xx-response': -1,
+        'operation-success-response': -1,
         'openapi-tags': 'off',
         'operation-tag-defined': 'off',
       }),
       ...omit(spectral.rules, [
         'oas3-valid-schema-example',
-        'operation-2xx-response',
+        'operation-success-response',
         'openapi-tags',
         'operation-tag-defined',
       ]),
@@ -659,9 +659,6 @@ responses:: !!foo
     const result = await spectral.run(invalidSchema);
 
     expect(result).toEqual([
-      expect.objectContaining({
-        code: 'openapi-tags',
-      }),
       expect.objectContaining({
         code: 'operation-tag-defined',
       }),
diff --git a/src/__tests__/spectral.jest.test.ts b/src/__tests__/spectral.jest.test.ts
index 7d60c6eb..1b0ff958 100644
--- a/src/__tests__/spectral.jest.test.ts
+++ b/src/__tests__/spectral.jest.test.ts
@@ -37,8 +37,8 @@ describe('Spectral', () => {
       expect(Object.entries(s.exceptions)).toEqual([
         [expect.stringMatching('^/test/file.json#/info$'), ['info-contact', 'info-description']],
         [expect.stringMatching('^/test/file.json#$'), ['oas3-api-servers']],
-        [expect.stringMatching('^/test/file.json#/paths/~1a.two/get$'), ['operation-2xx-response']],
-        [expect.stringMatching('^/test/file.json#/paths/~1b.three/get$'), ['operation-2xx-response']],
+        [expect.stringMatching('^/test/file.json#/paths/~1a.two/get$'), ['operation-success-response']],
+        [expect.stringMatching('^/test/file.json#/paths/~1b.three/get$'), ['operation-success-response']],
         [expect.stringMatching('/__tests__/__fixtures__/another.yaml#$'), ['dummy-rule', 'info-contact']],
       ]);
     });
diff --git a/src/cli/services/__tests__/linter.test.ts b/src/cli/services/__tests__/linter.test.ts
index 2660ff3a..3abbbcdc 100644
--- a/src/cli/services/__tests__/linter.test.ts
+++ b/src/cli/services/__tests__/linter.test.ts
@@ -229,57 +229,57 @@ describe('Linter service', () => {
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.invalid-schema.oas3.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/pet', 'post', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/pet', 'put', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/pet/{petId}', 'post', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/pet/{petId}', 'delete', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/store/order/{orderId}', 'delete', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/user', 'post', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/user/createWithArray', 'post', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/user/createWithList', 'post', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/user/logout', 'get', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/user/{username}', 'put', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
           expect.objectContaining({
-            code: 'operation-2xx-response',
+            code: 'operation-success-response',
             path: ['paths', '/user/{username}', 'delete', 'responses'],
             source: join(process.cwd(), 'src/__tests__/__fixtures__/petstore.oas2.json'),
           }),
@@ -559,13 +559,6 @@ describe('Linter service', () => {
           range: expect.any(Object),
           source: expect.stringContaining('__tests__/__fixtures__/draft-ref.oas2.json'),
         }),
-        expect.objectContaining({
-          code: 'openapi-tags',
-          message: 'OpenAPI object should have non-empty `tags` array.',
-          path: [],
-          range: expect.any(Object),
-          source: expect.stringContaining('__tests__/__fixtures__/draft-ref.oas2.json'),
-        }),
         expect.objectContaining({
           code: 'oas2-schema',
           message: 'Property `foo` is not expected to be here.',
@@ -642,13 +635,6 @@ describe('Linter service', () => {
           range: expect.any(Object),
           source: expect.stringContaining('__tests__/__fixtures__/draft-nested-ref.oas2.json'),
         }),
-        expect.objectContaining({
-          code: 'openapi-tags',
-          message: 'OpenAPI object should have non-empty `tags` array.',
-          path: [],
-          range: expect.any(Object),
-          source: expect.stringContaining('__tests__/__fixtures__/draft-nested-ref.oas2.json'),
-        }),
         expect.objectContaining({
           code: 'oas2-schema',
           message: '`info` property should have required property `title`.',
@@ -765,10 +751,6 @@ describe('Linter service', () => {
             code: 'oas3-api-servers',
             source: 'foo://openapi-3.0-no-contact.yaml',
           }),
-          expect.objectContaining({
-            code: 'openapi-tags',
-            source: 'foo://openapi-3.0-no-contact.yaml',
-          }),
         ]),
       );
     });
diff --git a/src/rulesets/__tests__/__fixtures__/extends-oas-with-override-ruleset.json b/src/rulesets/__tests__/__fixtures__/extends-oas-with-override-ruleset.json
index 47b6f856..cb3efd59 100644
--- a/src/rulesets/__tests__/__fixtures__/extends-oas-with-override-ruleset.json
+++ b/src/rulesets/__tests__/__fixtures__/extends-oas-with-override-ruleset.json
@@ -2,7 +2,7 @@
   "extends": [["spectral:oas", "all"]],
   "rules": {
     "oas2-operation-security-defined": "off",
-    "operation-2xx-response": {
+    "operation-success-response": {
       "description": "should be overridden",
       "given": "$.info",
       "recommended": true,
diff --git a/src/rulesets/__tests__/reader.jest.test.ts b/src/rulesets/__tests__/reader.jest.test.ts
index 4a7e69c4..d66fc7b4 100644
--- a/src/rulesets/__tests__/reader.jest.test.ts
+++ b/src/rulesets/__tests__/reader.jest.test.ts
@@ -294,7 +294,7 @@ describe('Rulesets reader', () => {
   });
 
   it('should override properties of extended rulesets', () => {
-    return expect(readRuleset(extendsOasWithOverrideRuleset)).resolves.toHaveProperty('rules.operation-2xx-response', {
+    return expect(readRuleset(extendsOasWithOverrideRuleset)).resolves.toHaveProperty('rules.operation-success-response', {
       description: 'should be overridden',
       given: '$.info',
       formats: expect.arrayContaining([expect.any(String)]),
@@ -875,7 +875,7 @@ describe('Rulesets reader', () => {
     });
 
     expect(functions).toMatchObject({
-      oasOp2xxResponse: expect.any(Object),
+      oasOpSuccessResponse: expect.any(Object),
       oasOpFormDataConsumeCheck: expect.any(Object),
       oasOpIdUnique: expect.any(Object),
       oasOpParams: expect.any(Object),
diff --git a/src/rulesets/__tests__/reader.karma.test.ts b/src/rulesets/__tests__/reader.karma.test.ts
index 3f1839e4..01e1aae5 100644
--- a/src/rulesets/__tests__/reader.karma.test.ts
+++ b/src/rulesets/__tests__/reader.karma.test.ts
@@ -36,7 +36,7 @@ describe('Rulesets reader', () => {
     });
 
     expect(functions).toMatchObject({
-      oasOp2xxResponse: expect.any(Object),
+      oasOpSuccessResponse: expect.any(Object),
       oasOpFormDataConsumeCheck: expect.any(Object),
       oasOpIdUnique: expect.any(Object),
       oasOpParams: expect.any(Object),
diff --git a/src/rulesets/mergers/__tests__/formats.test.ts b/src/rulesets/mergers/__tests__/formats.test.ts
index 8d94a609..b82056f3 100644
--- a/src/rulesets/mergers/__tests__/formats.test.ts
+++ b/src/rulesets/mergers/__tests__/formats.test.ts
@@ -3,12 +3,12 @@ import { mergeFormats } from '../formats';
 
 describe('Ruleset formats merging', () => {
   const baseRule: IRule = {
-    message: 'Operation must have at least one `2xx` response.',
+    message: 'Operation must have at least one `2xx` or `3xx` response.',
     given:
       "$.paths.*[?( @property === 'get' || @property === 'put' || @property === 'post' || @property === 'delete' || @property === 'options' || @property === 'head' || @property === 'patch' || @property === 'trace' )]",
     then: {
       field: 'responses',
-      function: 'oasOp2xxResponse',
+      function: 'oasOpSuccessResponse',
       functionOptions: {
         foo: 'bar',
       },
diff --git a/src/rulesets/mergers/__tests__/rules.test.ts b/src/rulesets/mergers/__tests__/rules.test.ts
index 3caf55a9..1348804c 100644
--- a/src/rulesets/mergers/__tests__/rules.test.ts
+++ b/src/rulesets/mergers/__tests__/rules.test.ts
@@ -5,12 +5,12 @@ import { mergeRules } from '../rules';
 
 describe('Ruleset rules merging', () => {
   const baseRule: IRule = {
-    message: 'Operation must have at least one `2xx` response.',
+    message: 'Operation must have at least one `2xx` or `3xx` response.',
     given:
       "$..paths.*[?( @property === 'get' || @property === 'put' || @property === 'post' || @property === 'delete' || @property === 'options' || @property === 'head' || @property === 'patch' || @property === 'trace' )]",
     then: {
       field: 'responses',
-      function: 'oasOp2xxResponse',
+      function: 'oasOpSuccessResponse',
       functionOptions: {
         foo: 'bar',
       },
@@ -77,12 +77,12 @@ describe('Ruleset rules merging', () => {
 
     mergeRules(rules, {
       test: {
-        message: 'Operation must have at least one `2xx` response.',
+        message: 'Operation must have at least one `2xx` or `3xx` response.',
         given:
           "$..paths.*[?( @property === 'get' || @property === 'put' || @property === 'post' || @property === 'delete' || @property === 'options' || @property === 'head' || @property === 'patch' || @property === 'trace' )]",
         then: {
           field: 'responses',
-          function: 'oasOp2xxResponse',
+          function: 'oasOpSuccessResponse',
         },
         severity: 'error',
       },
@@ -98,12 +98,12 @@ describe('Ruleset rules merging', () => {
 
     mergeRules(rules, {
       test: {
-        message: 'Operation must have at least one `2xx` response.',
+        message: 'Operation must have at least one `2xx` or `3xx` response.',
         given:
           "$..paths.*[?( @property === 'get' || @property === 'put' || @property === 'post' || @property === 'delete' || @property === 'options' || @property === 'head' || @property === 'patch' || @property === 'trace' )]",
         then: {
           field: 'responses',
-          function: 'oasOp2xxResponse',
+          function: 'oasOpSuccessResponse',
         },
         severity: 'error',
       },
diff --git a/src/rulesets/oas/__tests__/operation-default-response.ts b/src/rulesets/oas/__tests__/operation-default-response.ts
deleted file mode 100644
index 2326c8ec..00000000
--- a/src/rulesets/oas/__tests__/operation-default-response.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { DiagnosticSeverity } from '@stoplight/types';
-import { RuleType, Spectral } from '../../../spectral';
-import * as ruleset from '../index.json';
-
-describe('operation-default-response', () => {
-  const s = new Spectral();
-  s.setRules({
-    'operation-default-response': Object.assign(ruleset.rules['operation-default-response'], {
-      recommended: true,
-      type: RuleType[ruleset.rules['operation-default-response'].type],
-    }),
-  });
-
-  test('validate a correct object', async () => {
-    const results = await s.run({
-      swagger: '2.0',
-      paths: {
-        '/path': {
-          '/get': {
-            responses: {
-              default: {},
-            },
-          },
-        },
-      },
-    });
-    expect(results).toHaveLength(0);
-  });
-
-  test('return errors if path-responses is missing default', async () => {
-    const results = await s.run({
-      swagger: '2.0',
-      paths: {
-        '/path': {
-          '/get': {
-            responses: {
-              '2xx': {},
-            },
-          },
-        },
-      },
-    });
-    expect(results).toEqual([
-      {
-        code: 'operation-default-response',
-        message: 'Operations must have a default response.',
-        path: ['paths', '/path', '/get', 'responses'],
-        range: {
-          end: {
-            character: 19,
-            line: 6,
-          },
-          start: {
-            character: 20,
-            line: 5,
-          },
-        },
-        severity: DiagnosticSeverity.Warning,
-      },
-    ]);
-  });
-});
diff --git a/src/rulesets/oas/__tests__/operation-2xx-response.ts b/src/rulesets/oas/__tests__/operation-success-response.ts
similarity index 65%
rename from src/rulesets/oas/__tests__/operation-2xx-response.ts
rename to src/rulesets/oas/__tests__/operation-success-response.ts
index fa1400ca..2e923ed9 100644
--- a/src/rulesets/oas/__tests__/operation-2xx-response.ts
+++ b/src/rulesets/oas/__tests__/operation-success-response.ts
@@ -1,16 +1,16 @@
 import { Spectral } from '../../../spectral';
-import oasOp2xxResponse from '../functions/oasOp2xxResponse';
+import oasOpSuccessResponse from '../functions/oasOpSuccessResponse';
 import { rules } from '../index.json';
 
-describe('operation-2xx-response', () => {
+describe('operation-success-response', () => {
   let spectral: Spectral;
 
   beforeEach(() => {
     spectral = new Spectral();
-    spectral.setFunctions({ oasOp2xxResponse });
+    spectral.setFunctions({ oasOpSuccessResponse });
     spectral.setRules({
       // @ts-ignore
-      'operation-2xx-response': rules['operation-2xx-response'],
+      'operation-success-response': rules['operation-success-response'],
     });
   });
 
@@ -31,7 +31,24 @@ describe('operation-2xx-response', () => {
     expect(results).toHaveLength(0);
   });
 
-  test('is happy when a (non 200) 2xx response is set', async () => {
+  test('is happy when a 301 response is set', async () => {
+    const results = await spectral.run({
+      swagger: '2.0',
+      paths: {
+        '/path': {
+          get: {
+            responses: {
+              '301': {},
+            },
+          },
+        },
+      },
+    });
+
+    expect(results).toHaveLength(0);
+  });
+
+  test('is happy when a (non 200) success response is set', async () => {
     const results = await spectral.run({
       swagger: '2.0',
       paths: {
@@ -49,7 +66,7 @@ describe('operation-2xx-response', () => {
   });
 
   ['put', 'post', 'delete', 'options', 'head', 'patch', 'trace'].forEach(method => {
-    test(`warns if HTTP verb ${method} is missing a 2xx response`, async () => {
+    test(`warns if HTTP verb ${method} is missing a success response`, async () => {
       const obj = {
         swagger: '2.0',
         paths: {
@@ -64,15 +81,15 @@ describe('operation-2xx-response', () => {
       const results = await spectral.run(obj);
       expect(results).toEqual([
         expect.objectContaining({
-          code: 'operation-2xx-response',
-          message: 'Operation must have at least one `2xx` response.',
+          code: 'operation-success-response',
+          message: 'Operation must have at least one `2xx` or `3xx` response.',
           path: ['paths', '/path', method, 'responses'],
         }),
       ]);
     });
   });
 
-  test('warns about missing 2xx response', async () => {
+  test('warns about missing success response', async () => {
     const results = await spectral.run({
       swagger: '2.0',
       paths: {
@@ -88,8 +105,8 @@ describe('operation-2xx-response', () => {
 
     expect(results).toEqual([
       expect.objectContaining({
-        code: 'operation-2xx-response',
-        message: 'Operation must have at least one `2xx` response.',
+        code: 'operation-success-response',
+        message: 'Operation must have at least one `2xx` or `3xx` response.',
         path: ['paths', '/path', 'get', 'responses'],
       }),
     ]);
diff --git a/src/rulesets/oas/functions/__tests__/oasOp2xxResponse.test.ts b/src/rulesets/oas/functions/__tests__/oasOpSuccessResponse.test.ts
similarity index 79%
rename from src/rulesets/oas/functions/__tests__/oasOp2xxResponse.test.ts
rename to src/rulesets/oas/functions/__tests__/oasOpSuccessResponse.test.ts
index 232fda4a..f66f5c59 100644
--- a/src/rulesets/oas/functions/__tests__/oasOp2xxResponse.test.ts
+++ b/src/rulesets/oas/functions/__tests__/oasOpSuccessResponse.test.ts
@@ -1,18 +1,18 @@
 import { DiagnosticSeverity } from '@stoplight/types/dist';
 import { RuleType, Spectral } from '../../../../spectral';
 import { rules } from '../../index.json';
-import oasOp2xxResponse from '../oasOp2xxResponse';
+import oasOpSuccessResponse from '../oasOpSuccessResponse';
 
-describe('oasOp2xxResponse', () => {
+describe('oasOpSuccessResponse', () => {
   let s: Spectral;
 
   beforeEach(() => {
     s = new Spectral();
-    s.setFunctions({ oasOp2xxResponse });
+    s.setFunctions({ oasOpSuccessResponse });
     s.setRules({
-      'operation-2xx-response': Object.assign(rules['operation-2xx-response'], {
+      'operation-success-response': Object.assign(rules['operation-success-response'], {
         recommended: true,
-        type: RuleType[rules['operation-2xx-response'].type],
+        type: RuleType[rules['operation-success-response'].type],
       }),
     });
   });
@@ -38,7 +38,7 @@ describe('oasOp2xxResponse', () => {
     expect(results.length).toEqual(0);
   });
 
-  test('return errors if missing 2xx', async () => {
+  test('return errors if missing Success', async () => {
     const results = await s.run({
       paths: {
         '/path1': {
@@ -59,8 +59,8 @@ describe('oasOp2xxResponse', () => {
 
     expect(results).toEqual([
       {
-        code: 'operation-2xx-response',
-        message: 'Operation must have at least one `2xx` response.',
+        code: 'operation-success-response',
+        message: 'Operation must have at least one `2xx` or `3xx` response.',
         path: ['paths', '/path1', 'get', 'responses'],
         range: {
           end: {
@@ -89,8 +89,8 @@ describe('oasOp2xxResponse', () => {
     });
     expect(results).toEqual([
       {
-        code: 'operation-2xx-response',
-        message: 'Operation must have at least one `2xx` response.',
+        code: 'operation-success-response',
+        message: 'Operation must have at least one `2xx` or `3xx` response.',
         path: ['paths', '/path1', 'get', 'responses'],
         range: {
           end: {