Repository: stoplightio/spectral
Pull request #182 (2019-05-07 10:13:06)

Feature/SO-170/convert oas2 and 3 rulesets to yaml
### Please check if the PR fulfills these requirements
- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)

### What kind of change does this PR introduce?

Feature

### What is the current behavior?

When using CLI we automatically detect oas2/3 files and add standard Stoplight rules based on the file type. We also allow users to provide their own ruleset files that can extend other ruleset files. However, our standard rules come in TypeScript file only and can't be extended from using the CLI ruleset feature.

### If this is a feature change, what is the new behavior?

This PR introduces three ruleset `yaml` files (oas.ruleset.yaml, oas2.ruleset.yaml, oas3.ruleset.yaml) that can be generated and kept up to date using the `yarn build.rulesets` command. These files mirror our TypeScript rules.

### Does this PR introduce a breaking change?

No



chris-miaskowski: For some reason (maybe a failed merge) it suddenly started complaining about tslint errors... I'm fixing all in this PR.
chris-miaskowski: @XVincentX thanks for the comments, really appreciate. If you haven't read through the whole thing can you do your second round before I address your requests? Commenting -> addressing -> commenting -> addressing will take too much time. Throw all you got at me and I will implement everything in one go.
chris-miaskowski: @XVincentX addressed everything.

Btw guys I hope you don't mind if I replace the ts-ignore with `as Rule` some other time? It's a refactoring that's nice to have but I'd rather boyscout it later.
chris-miaskowski: @XVincentX I'm done, rereview pls
chris-miaskowski: Thanks for helping me resolve the conflicts Jakub!
philsturgeon: Ugh. Ship. 😅
chris-miaskowski: > Ugh. Ship.

Freudian slip! :P

Patch:
diff --git a/package.json b/package.json
index 70813f6c..931e7ed4 100644
--- a/package.json
+++ b/package.json
@@ -40,8 +40,10 @@
   },
   "scripts": {
     "build": "sl-scripts build && node ./scripts/prepare-cli",
+    "postbuild": "yarn copy.rulesets --verbose",
     "build.binary": "yarn build && yarn build.manifest && cp yarn.lock dist && cd dist && yarn && pkg . --out-path ./bin",
     "build.manifest": "cd dist && oclif-dev manifest",
+    "copy.rulesets": "copyfiles -u 1 \"src/**/ruleset.json\" dist",
     "commit": "git-cz",
     "lint": "tslint 'src/**/*.ts'",
     "lint.fix": "yarn lint --fix",
@@ -84,15 +86,19 @@
     "@types/node": "12.0.x",
     "@types/strip-ansi": "^5.2.1",
     "@types/text-table": "^0.2.0",
+    "@types/yaml": "^1.0.2",
+    "copyfiles": "^2.1.0",
     "fs-extra": "^7.0.1",
     "jest": "24.8.x",
     "jest-when": "^2.4.0",
     "nock": "^10.0.6",
     "pkg": "4.4.0",
     "ts-jest": "24.0.x",
+    "ts-node": "^8.1.0",
     "tslint": "5.16.0",
     "tslint-config-stoplight": "1.3.0",
-    "typescript": "3.4.5"
+    "typescript": "3.4.5",
+    "yaml": "^1.5.1"
   },
   "lint-staged": {
     "*.{ts,tsx}": [
diff --git a/src/cli/commands/lint.ts b/src/cli/commands/lint.ts
index 3f8bf12d..d8a8cf12 100644
--- a/src/cli/commands/lint.ts
+++ b/src/cli/commands/lint.ts
@@ -9,9 +9,9 @@ import { IRuleResult } from '../..';
 import { createEmptyConfig, getDefaultConfigFile, load as loadConfig } from '../../config/configLoader';
 import { json, stylish } from '../../formatters';
 import { readParsable } from '../../fs/reader';
-import { oas2Functions, oas2Rules } from '../../rulesets/oas2';
-import { oas3Functions, oas3Rules } from '../../rulesets/oas3';
-import { readRulesets } from '../../rulesets/reader';
+import { oas2Functions, rules as oas2Rules } from '../../rulesets/oas2';
+import { oas3Functions, rules as oas3Rules } from '../../rulesets/oas3';
+import { readRulesFromRulesets } from '../../rulesets/reader';
 import { Spectral } from '../../spectral';
 import { IParsedResult, RuleCollection } from '../../types';
 import { ConfigCommand, IConfig, ILintConfig } from '../../types/config';
@@ -90,11 +90,9 @@ linting ./openapi.yaml
     let rules;
 
     if (ruleset) {
-      try {
-        rules = await readRulesets(this, ...ruleset);
-      } catch (ex) {
-        this.error(ex.message);
-      }
+      rules = await tryReadOrLog(this, async () => {
+        return readRulesFromRulesets(...ruleset);
+      });
     }
 
     if (args.source) {
@@ -109,13 +107,34 @@ linting ./openapi.yaml
   }
 }
 
+async function tryReadOrLog(command: Lint, reader: Function) {
+  try {
+    return await reader();
+  } catch (ex) {
+    if (ex.messages) {
+      command.log(ex.messages[0]);
+      command.error(ex.messages[1]);
+    } else {
+      command.error(ex);
+    }
+  }
+}
+
 async function lint(name: string, flags: any, command: Lint, rules?: RuleCollection) {
   if (flags.verbose) {
     command.log(`Linting ${name}`);
   }
   const spec: IParserResult = await readParsable(name, flags.encoding);
   const spectral = new Spectral();
-  if (rules !== undefined) {
+  if (parseInt(spec.data.swagger) === 2) {
+    command.log('Adding OpenAPI 2.0 (Swagger) functions');
+    spectral.addFunctions(oas2Functions());
+  } else if (parseInt(spec.data.openapi) === 3) {
+    command.log('Adding OpenAPI 3.x functions');
+    spectral.addFunctions(oas3Functions());
+  }
+
+  if (rules) {
     if (flags.verbose) {
       command.log(`Found ${Object.keys(rules).length} rules`);
     }
@@ -125,12 +144,10 @@ async function lint(name: string, flags: any, command: Lint, rules?: RuleCollect
     }
     if (parseInt(spec.data.swagger) === 2) {
       command.log('OpenAPI 2.0 (Swagger) detected');
-      spectral.addFunctions(oas2Functions());
-      rules = oas2Rules();
+      rules = await tryReadOrLog(command, async () => await oas2Rules());
     } else if (parseInt(spec.data.openapi) === 3) {
       command.log('OpenAPI 3.x detected');
-      spectral.addFunctions(oas3Functions());
-      rules = oas3Rules();
+      rules = await tryReadOrLog(command, async () => await oas3Rules());
     }
   }
 
diff --git a/src/rulesets/index.ts b/src/rulesets/index.ts
index fadc5d8c..12e2969e 100644
--- a/src/rulesets/index.ts
+++ b/src/rulesets/index.ts
@@ -1,10 +1,12 @@
-import { oas2Functions, oas2Rules } from './oas2';
-import { oas3Functions, oas3Rules } from './oas3';
+import { oas2Functions } from './oas2';
+import * as oas2Ruleset from './oas2/ruleset.json';
+import { oas3Functions } from './oas3';
+import * as oas3Ruleset from './oas3/ruleset.json';
 
 const merge = require('lodash/merge');
 
 export const defaultRules = () => {
-  return merge(oas2Rules(), oas3Rules());
+  return merge(oas2Ruleset.rules, oas3Ruleset.rules);
 };
 
 export const defaultFunctions = () => {
diff --git a/src/rulesets/oas/index.ts b/src/rulesets/oas/index.ts
index df7b2efa..045411dd 100644
--- a/src/rulesets/oas/index.ts
+++ b/src/rulesets/oas/index.ts
@@ -1,5 +1,6 @@
-import { DiagnosticSeverity } from '@stoplight/types';
-import { FunctionCollection, RuleCollection, RuleFunction, RuleType } from '../../types';
+import { resolve } from 'path';
+import { FunctionCollection } from '../../types';
+import { readRulesFromRulesets } from '../reader';
 
 export const operationPath =
   "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post'" +
@@ -17,363 +18,6 @@ export const commonOasFunctions = (): FunctionCollection => {
   };
 };
 
-export const commonOasRules = (): RuleCollection => ({
-  // Custom Rules
-
-  'operation-2xx-response': {
-    summary: 'Operation must have at least one `2xx` response.',
-    type: RuleType.STYLE,
-    given: operationPath,
-    then: {
-      field: 'responses',
-      function: 'oasOp2xxResponse',
-    },
-    tags: ['operation'],
-  },
-  'operation-formData-consume-check': {
-    summary:
-      'Operations with an `in: formData` parameter must include `application/x-www-form-urlencoded` or `multipart/form-data` in their `consumes` property.',
-    type: RuleType.VALIDATION,
-    given: operationPath,
-    then: {
-      function: 'oasOpFormDataConsumeCheck',
-    },
-    tags: ['operation'],
-  },
-  'operation-operationId-unique': {
-    summary: 'Every operation must have a unique `operationId`.',
-    type: RuleType.VALIDATION,
-    severity: DiagnosticSeverity.Error,
-    given: '$',
-    then: {
-      function: 'oasOpIdUnique',
-    },
-    tags: ['operation'],
-  },
-
-  'operation-parameters': {
-    summary: 'Operation parameters are unique and non-repeating.',
-    type: RuleType.VALIDATION,
-    given: '$',
-    then: {
-      function: 'oasOpParams',
-    },
-    tags: ['operation'],
-  },
-  'path-params': {
-    summary: 'Path parameters are correct and valid.',
-    message: '{{error}}',
-    type: RuleType.VALIDATION,
-    severity: DiagnosticSeverity.Error,
-    given: '$',
-    then: {
-      function: 'oasPathParam',
-    },
-    tags: ['given'],
-  },
-
-  // Generic Rules
-  'contact-properties': {
-    enabled: false,
-    summary: 'Contact object should have `name`, `url` and `email`.',
-    type: RuleType.STYLE,
-    given: '$.info.contact',
-    then: [
-      {
-        field: 'name',
-        function: RuleFunction.TRUTHY,
-      },
-      {
-        field: 'url',
-        function: RuleFunction.TRUTHY,
-      },
-      {
-        field: 'email',
-        function: RuleFunction.TRUTHY,
-      },
-    ],
-    tags: ['api'],
-  },
-  'example-value-or-externalValue': {
-    enabled: false,
-    summary: 'Example should have either a `value` or `externalValue` field.',
-    type: RuleType.STYLE,
-    given: '$..example',
-    then: {
-      function: RuleFunction.XOR,
-      functionOptions: {
-        properties: ['externalValue', 'value'],
-      },
-    },
-  },
-  'info-contact': {
-    summary: 'Info object should contain `contact` object.',
-    type: RuleType.STYLE,
-    given: '$',
-    then: {
-      field: 'info.contact',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['api'],
-  },
-  'info-description': {
-    summary: 'OpenAPI object info `description` must be present and non-empty string.',
-    type: RuleType.STYLE,
-    given: '$',
-    then: {
-      field: 'info.description',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['api'],
-  },
-  'info-license': {
-    enabled: false,
-    summary: 'OpenAPI object info `license` must be present and non-empty string.',
-    type: RuleType.STYLE,
-    given: '$',
-    then: {
-      field: 'info.license',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['api'],
-  },
-  'license-url': {
-    enabled: false,
-    summary: 'License object should include `url`.',
-    type: RuleType.STYLE,
-    given: '$',
-    then: {
-      field: 'info.license.url',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['api'],
-  },
-  'no-eval-in-markdown': {
-    enabled: false,
-    summary: 'Markdown descriptions should not contain `eval(`.',
-    type: RuleType.STYLE,
-    given: '$..*',
-    then: [
-      {
-        field: 'description',
-        function: RuleFunction.PATTERN,
-        functionOptions: {
-          notMatch: 'eval\\(',
-        },
-      },
-      {
-        field: 'title',
-        function: RuleFunction.PATTERN,
-        functionOptions: {
-          notMatch: 'eval\\(',
-        },
-      },
-    ],
-  },
-  'no-script-tags-in-markdown': {
-    summary: 'Markdown descriptions should not contain `<script>` tags.',
-    type: RuleType.STYLE,
-    given: '$..*',
-    then: [
-      {
-        field: 'description',
-        function: RuleFunction.PATTERN,
-        functionOptions: {
-          notMatch: '<script',
-        },
-      },
-      {
-        field: 'title',
-        function: RuleFunction.PATTERN,
-        functionOptions: {
-          notMatch: '<script',
-        },
-      },
-    ],
-  },
-  'only-local-references': {
-    enabled: false,
-    summary: 'References should start with `#/`.',
-    type: RuleType.STYLE,
-    given: "$..['$ref']",
-    then: {
-      function: RuleFunction.PATTERN,
-      functionOptions: {
-        match: '^#\\/',
-      },
-    },
-    tags: ['references'],
-  },
-  'openapi-tags-alphabetical': {
-    enabled: false,
-    summary: 'OpenAPI object should have alphabetical `tags`.',
-    type: RuleType.STYLE,
-    given: '$',
-    then: {
-      field: 'tags',
-      function: RuleFunction.ALPHABETICAL,
-      functionOptions: {
-        keyedBy: 'name',
-      },
-    },
-    tags: ['api'],
-  },
-  'openapi-tags': {
-    enabled: false,
-    summary: 'OpenAPI object should have non-empty `tags` array.',
-    type: RuleType.STYLE,
-    given: '$',
-    then: {
-      field: 'tags',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['api'],
-  },
-  'operation-default-response': {
-    enabled: false,
-    summary: 'Operations must have a default response.',
-    type: RuleType.STYLE,
-    given: '$..paths.*.*.responses',
-    then: {
-      field: 'default',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['operation'],
-  },
-  'operation-description': {
-    summary: 'Operation `description` must be present and non-empty string.',
-    type: RuleType.STYLE,
-    given: operationPath,
-    then: {
-      field: 'description',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['operation'],
-  },
-  'operation-operationId': {
-    summary: 'Operation should have an `operationId`.',
-    type: RuleType.STYLE,
-    given: operationPath,
-    then: {
-      field: 'operationId',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['operation'],
-  },
-  'operation-operationId-valid-in-url': {
-    summary: 'operationId may only use characters that are valid when used in a URL.',
-    type: RuleType.VALIDATION,
-    given: operationPath,
-    then: {
-      field: 'operationId',
-      function: RuleFunction.PATTERN,
-      functionOptions: {
-        match: `^[A-Za-z0-9-._~:/?#\\[\\]@!\\$&'()*+,;=]*$`,
-      },
-    },
-    tags: ['operation'],
-  },
-  'operation-singular-tag': {
-    enabled: false,
-    summary: 'Operation may only have one tag.',
-    type: RuleType.STYLE,
-    given: operationPath,
-    then: {
-      field: 'tags',
-      function: RuleFunction.LENGTH,
-      functionOptions: {
-        max: 1,
-      },
-    },
-    tags: ['operation'],
-  },
-  'operation-summary-formatted': {
-    enabled: false,
-    summary: 'Operation `summary` should start with upper case and end with a dot.',
-    type: RuleType.STYLE,
-    given: operationPath,
-    then: {
-      field: 'summary',
-      function: RuleFunction.PATTERN,
-      functionOptions: {
-        match: '^[A-Z].*\\.$',
-      },
-    },
-    tags: ['operation'],
-  },
-  'operation-tags': {
-    summary: 'Operation should have non-empty `tags` array.',
-    type: RuleType.STYLE,
-    given: operationPath,
-    then: {
-      field: 'tags',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['operation'],
-  },
-  'parameter-description': {
-    enabled: false,
-    summary: 'Parameter objects should have a `description`.',
-    type: RuleType.STYLE,
-    given: '$..parameters[*]',
-    when: {
-      field: '@key',
-      pattern: '^(?!.*(\\$ref))',
-    },
-    then: {
-      field: 'description',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['parameters'],
-  },
-  'path-declarations-must-exist': {
-    summary: 'given declarations cannot be empty, ex.`/given/{}` is invalid.',
-    type: RuleType.STYLE,
-    given: '$..paths',
-    then: {
-      field: '@key',
-      function: RuleFunction.PATTERN,
-      functionOptions: {
-        notMatch: '{}',
-      },
-    },
-    tags: ['given'],
-  },
-  'path-keys-no-trailing-slash': {
-    summary: 'given keys should not end with a slash.',
-    type: RuleType.STYLE,
-    given: '$..paths',
-    then: {
-      field: '@key',
-      function: RuleFunction.PATTERN,
-      functionOptions: {
-        notMatch: '.+\\/$',
-      },
-    },
-    tags: ['given'],
-  },
-  'path-not-include-query': {
-    summary: 'given keys should not include a query string.',
-    type: RuleType.STYLE,
-    given: '$..paths',
-    then: {
-      field: '@key',
-      function: RuleFunction.PATTERN,
-      functionOptions: {
-        notMatch: '\\?',
-      },
-    },
-    tags: ['given'],
-  },
-  'tag-description': {
-    enabled: false,
-    summary: 'Tag object should have a `description`.',
-    type: RuleType.STYLE,
-    given: '$.tags[*]',
-    then: {
-      field: 'description',
-      function: RuleFunction.TRUTHY,
-    },
-    tags: ['api'],
-  },
-});
+export const rules = async () => {
+  return readRulesFromRulesets(resolve(__dirname, 'ruleset.json'));
+};
diff --git a/src/rulesets/oas/ruleset.json b/src/rulesets/oas/ruleset.json
new file mode 100644
index 00000000..265c45b3
--- /dev/null
+++ b/src/rulesets/oas/ruleset.json
@@ -0,0 +1,409 @@
+{
+  "rules": {
+    "operation-2xx-response": {
+      "summary": "Operation must have at least one `2xx` response.",
+      "type": "style",
+      "given": "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post' || name() === 'delete' || name() === 'options' || name() === 'head' || name() === 'patch' || name() === 'trace' )]",
+      "then": {
+        "field": "responses",
+        "function": "oasOp2xxResponse"
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-formData-consume-check": {
+      "summary": "Operations with an `in: formData` parameter must include `application/x-www-form-urlencoded` or `multipart/form-data` in their `consumes` property.",
+      "type": "validation",
+      "given": "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post' || name() === 'delete' || name() === 'options' || name() === 'head' || name() === 'patch' || name() === 'trace' )]",
+      "then": {
+        "function": "oasOpFormDataConsumeCheck"
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-operationId-unique": {
+      "summary": "Every operation must have a unique `operationId`.",
+      "type": "validation",
+      "severity": 0,
+      "given": "$",
+      "then": {
+        "function": "oasOpIdUnique"
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-parameters": {
+      "summary": "Operation parameters are unique and non-repeating.",
+      "type": "validation",
+      "given": "$",
+      "then": {
+        "function": "oasOpParams"
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "path-params": {
+      "summary": "Path parameters are correct and valid.",
+      "message": "{{error}}",
+      "type": "validation",
+      "severity": 0,
+      "given": "$",
+      "then": {
+        "function": "oasPathParam"
+      },
+      "tags": [
+        "given"
+      ]
+    },
+    "contact-properties": {
+      "enabled": false,
+      "summary": "Contact object should have `name`, `url` and `email`.",
+      "type": "style",
+      "given": "$.info.contact",
+      "then": [
+        {
+          "field": "name",
+          "function": "truthy"
+        },
+        {
+          "field": "url",
+          "function": "truthy"
+        },
+        {
+          "field": "email",
+          "function": "truthy"
+        }
+      ],
+      "tags": [
+        "api"
+      ]
+    },
+    "example-value-or-externalValue": {
+      "enabled": false,
+      "summary": "Example should have either a `value` or `externalValue` field.",
+      "type": "style",
+      "given": "$..example",
+      "then": {
+        "function": "xor",
+        "functionOptions": {
+          "properties": [
+            "externalValue",
+            "value"
+          ]
+        }
+      }
+    },
+    "info-contact": {
+      "summary": "Info object should contain `contact` object.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "info.contact",
+        "function": "truthy"
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "info-description": {
+      "summary": "OpenAPI object info `description` must be present and non-empty string.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "info.description",
+        "function": "truthy"
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "info-license": {
+      "enabled": false,
+      "summary": "OpenAPI object info `license` must be present and non-empty string.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "info.license",
+        "function": "truthy"
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "license-url": {
+      "enabled": false,
+      "summary": "License object should include `url`.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "info.license.url",
+        "function": "truthy"
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "no-eval-in-markdown": {
+      "enabled": false,
+      "summary": "Markdown descriptions should not contain `eval(`.",
+      "type": "style",
+      "given": "$..*",
+      "then": [
+        {
+          "field": "description",
+          "function": "pattern",
+          "functionOptions": {
+            "notMatch": "eval\\("
+          }
+        },
+        {
+          "field": "title",
+          "function": "pattern",
+          "functionOptions": {
+            "notMatch": "eval\\("
+          }
+        }
+      ]
+    },
+    "no-script-tags-in-markdown": {
+      "summary": "Markdown descriptions should not contain `<script>` tags.",
+      "type": "style",
+      "given": "$..*",
+      "then": [
+        {
+          "field": "description",
+          "function": "pattern",
+          "functionOptions": {
+            "notMatch": "<script"
+          }
+        },
+        {
+          "field": "title",
+          "function": "pattern",
+          "functionOptions": {
+            "notMatch": "<script"
+          }
+        }
+      ]
+    },
+    "only-local-references": {
+      "enabled": false,
+      "summary": "References should start with `#/`.",
+      "type": "style",
+      "given": "$..['$ref']",
+      "then": {
+        "function": "pattern",
+        "functionOptions": {
+          "match": "^#\\/"
+        }
+      },
+      "tags": [
+        "references"
+      ]
+    },
+    "openapi-tags-alphabetical": {
+      "enabled": false,
+      "summary": "OpenAPI object should have alphabetical `tags`.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "tags",
+        "function": "alphabetical",
+        "functionOptions": {
+          "keyedBy": "name"
+        }
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "openapi-tags": {
+      "enabled": false,
+      "summary": "OpenAPI object should have non-empty `tags` array.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "tags",
+        "function": "truthy"
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "operation-default-response": {
+      "enabled": false,
+      "summary": "Operations must have a default response.",
+      "type": "style",
+      "given": "$..paths.*.*.responses",
+      "then": {
+        "field": "default",
+        "function": "truthy"
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-description": {
+      "summary": "Operation `description` must be present and non-empty string.",
+      "type": "style",
+      "given": "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post' || name() === 'delete' || name() === 'options' || name() === 'head' || name() === 'patch' || name() === 'trace' )]",
+      "then": {
+        "field": "description",
+        "function": "truthy"
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-operationId": {
+      "summary": "Operation should have an `operationId`.",
+      "type": "style",
+      "given": "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post' || name() === 'delete' || name() === 'options' || name() === 'head' || name() === 'patch' || name() === 'trace' )]",
+      "then": {
+        "field": "operationId",
+        "function": "truthy"
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-operationId-valid-in-url": {
+      "summary": "operationId may only use characters that are valid when used in a URL.",
+      "type": "validation",
+      "given": "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post' || name() === 'delete' || name() === 'options' || name() === 'head' || name() === 'patch' || name() === 'trace' )]",
+      "then": {
+        "field": "operationId",
+        "function": "pattern",
+        "functionOptions": {
+          "match": "^[A-Za-z0-9-._~:/?#\\[\\]@!\\$&'()*+,;=]*$"
+        }
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-singular-tag": {
+      "enabled": false,
+      "summary": "Operation may only have one tag.",
+      "type": "style",
+      "given": "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post' || name() === 'delete' || name() === 'options' || name() === 'head' || name() === 'patch' || name() === 'trace' )]",
+      "then": {
+        "field": "tags",
+        "function": "length",
+        "functionOptions": {
+          "max": 1
+        }
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-summary-formatted": {
+      "enabled": false,
+      "summary": "Operation `summary` should start with upper case and end with a dot.",
+      "type": "style",
+      "given": "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post' || name() === 'delete' || name() === 'options' || name() === 'head' || name() === 'patch' || name() === 'trace' )]",
+      "then": {
+        "field": "summary",
+        "function": "pattern",
+        "functionOptions": {
+          "match": "^[A-Z].*\\.$"
+        }
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "operation-tags": {
+      "summary": "Operation should have non-empty `tags` array.",
+      "type": "style",
+      "given": "$..paths.*[?( name() === 'get' || name() === 'put' || name() === 'post' || name() === 'delete' || name() === 'options' || name() === 'head' || name() === 'patch' || name() === 'trace' )]",
+      "then": {
+        "field": "tags",
+        "function": "truthy"
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "parameter-description": {
+      "enabled": false,
+      "summary": "Parameter objects should have a `description`.",
+      "type": "style",
+      "given": "$..parameters[*]",
+      "when": {
+        "field": "@key",
+        "pattern": "^(?!.*(\\$ref))"
+      },
+      "then": {
+        "field": "description",
+        "function": "truthy"
+      },
+      "tags": [
+        "parameters"
+      ]
+    },
+    "path-declarations-must-exist": {
+      "summary": "given declarations cannot be empty, ex.`/given/{}` is invalid.",
+      "type": "style",
+      "given": "$..paths",
+      "then": {
+        "field": "@key",
+        "function": "pattern",
+        "functionOptions": {
+          "notMatch": "{}"
+        }
+      },
+      "tags": [
+        "given"
+      ]
+    },
+    "path-keys-no-trailing-slash": {
+      "summary": "given keys should not end with a slash.",
+      "type": "style",
+      "given": "$..paths",
+      "then": {
+        "field": "@key",
+        "function": "pattern",
+        "functionOptions": {
+          "notMatch": ".+\\/$"
+        }
+      },
+      "tags": [
+        "given"
+      ]
+    },
+    "path-not-include-query": {
+      "summary": "given keys should not include a query string.",
+      "type": "style",
+      "given": "$..paths",
+      "then": {
+        "field": "@key",
+        "function": "pattern",
+        "functionOptions": {
+          "notMatch": "\\?"
+        }
+      },
+      "tags": [
+        "given"
+      ]
+    },
+    "tag-description": {
+      "enabled": false,
+      "summary": "Tag object should have a `description`.",
+      "type": "style",
+      "given": "$.tags[*]",
+      "then": {
+        "field": "description",
+        "function": "truthy"
+      },
+      "tags": [
+        "api"
+      ]
+    }
+  }
+}
diff --git a/src/rulesets/oas2/index.ts b/src/rulesets/oas2/index.ts
index d3edd31b..21af9586 100644
--- a/src/rulesets/oas2/index.ts
+++ b/src/rulesets/oas2/index.ts
@@ -1,116 +1,8 @@
-const merge = require('lodash/merge');
-
-import { DiagnosticSeverity } from '@stoplight/types';
-import { RuleFunction, RuleType } from '../../types';
-import { commonOasRules } from '../oas';
-import * as schema from './schemas/main.json';
+import { resolve } from 'path';
+import { readRulesFromRulesets } from '../reader';
 
 export { commonOasFunctions as oas2Functions } from '../oas';
 
-export const oas2Rules = () => {
-  return merge(commonOasRules(), {
-    // specification validation
-    'oas2-schema': {
-      message: '{{error}}',
-      type: RuleType.VALIDATION,
-      severity: DiagnosticSeverity.Error,
-      then: {
-        function: RuleFunction.SCHEMA,
-        functionOptions: {
-          schema,
-        },
-      },
-      tags: ['schema'],
-    },
-
-    // generic
-    'api-host': {
-      message: 'OpenAPI `host` must be present and non-empty string.',
-      type: RuleType.STYLE,
-      given: '$',
-      then: {
-        field: 'host',
-        function: RuleFunction.TRUTHY,
-      },
-      tags: ['api'],
-    },
-    'api-schemes': {
-      message: 'OpenAPI host `schemes` must be present and non-empty array.',
-      type: RuleType.STYLE,
-      given: '$',
-      then: {
-        field: 'schemes',
-        function: RuleFunction.SCHEMA,
-        functionOptions: {
-          schema: {
-            items: {
-              type: 'string',
-            },
-            minItems: 1,
-            type: 'array',
-          },
-        },
-      },
-      tags: ['api'],
-    },
-    'host-not-example': {
-      enabled: false,
-      message: 'Server URL should not point at `example.com`.',
-      type: RuleType.STYLE,
-      given: '$',
-      then: {
-        field: 'host',
-        function: RuleFunction.PATTERN,
-        functionOptions: {
-          notMatch: 'example.com',
-        },
-      },
-    },
-    'host-trailing-slash': {
-      message: 'Server URL should not have a trailing slash.',
-      type: RuleType.STYLE,
-      given: '$',
-      then: {
-        field: 'host',
-        function: RuleFunction.PATTERN,
-        functionOptions: {
-          notMatch: '/$',
-        },
-      },
-    },
-    'model-description': {
-      enabled: false,
-      message: 'Definition `description` must be present and non-empty string.',
-      type: RuleType.STYLE,
-      given: '$..definitions[*]',
-      then: {
-        field: 'description',
-        function: RuleFunction.TRUTHY,
-      },
-    },
-    'operation-security-defined': {
-      message: 'Operation `security` values must match a scheme defined in the `securityDefinitions` object.',
-      type: RuleType.VALIDATION,
-      given: '$',
-      then: {
-        function: 'oasOpSecurityDefined',
-        functionOptions: {
-          schemesPath: ['securityDefinitions'],
-        },
-      },
-      tags: ['operation'],
-    },
-    'valid-example': {
-      message: '"{{property}}" property {{error}}',
-      type: RuleType.VALIDATION,
-      given: '$..[?(@.example)]',
-      then: {
-        function: RuleFunction.SCHEMAPATH,
-        functionOptions: {
-          field: 'example',
-          schemaPath: '$',
-        },
-      },
-    },
-  });
+export const rules = async () => {
+  return readRulesFromRulesets(resolve(__dirname, 'ruleset.json'));
 };
diff --git a/src/rulesets/oas2/ruleset.json b/src/rulesets/oas2/ruleset.json
new file mode 100644
index 00000000..b7be1340
--- /dev/null
+++ b/src/rulesets/oas2/ruleset.json
@@ -0,0 +1,1740 @@
+{
+  "extends": [
+    "../oas/ruleset.json"
+  ],
+  "rules": {
+    "oas2-schema": {
+      "summary": "Validate structure of OpenAPIv2 specification.",
+      "message": "{{error}}",
+      "type": "validation",
+      "severity": 0,
+      "given": "$",
+      "then": {
+        "function": "schema",
+        "functionOptions": {
+          "schema": {
+            "title": "A JSON Schema for Swagger 2.0 API.",
+            "id": "http://swagger.io/v2/schema.json#",
+            "$schema": "http://json-schema.org/draft-04/schema#",
+            "type": "object",
+            "required": [
+              "swagger",
+              "info",
+              "paths"
+            ],
+            "additionalProperties": false,
+            "patternProperties": {
+              "^x-": {
+                "$ref": "#/definitions/vendorExtension"
+              }
+            },
+            "properties": {
+              "swagger": {
+                "type": "string",
+                "enum": [
+                  "2.0"
+                ],
+                "description": "The Swagger version of this document."
+              },
+              "info": {
+                "$ref": "#/definitions/info"
+              },
+              "host": {
+                "type": "string",
+                "pattern": "^[^{}/ :\\\\]+(?::\\d+)?$",
+                "description": "The host (name or ip) of the API. Example: 'swagger.io'"
+              },
+              "basePath": {
+                "type": "string",
+                "pattern": "^/",
+                "description": "The base path to the API. Example: '/api'."
+              },
+              "schemes": {
+                "$ref": "#/definitions/schemesList"
+              },
+              "consumes": {
+                "description": "A list of MIME types accepted by the API.",
+                "allOf": [
+                  {
+                    "$ref": "#/definitions/mediaTypeList"
+                  }
+                ]
+              },
+              "produces": {
+                "description": "A list of MIME types the API can produce.",
+                "allOf": [
+                  {
+                    "$ref": "#/definitions/mediaTypeList"
+                  }
+                ]
+              },
+              "paths": {
+                "$ref": "#/definitions/paths"
+              },
+              "definitions": {
+                "$ref": "#/definitions/definitions"
+              },
+              "parameters": {
+                "$ref": "#/definitions/parameterDefinitions"
+              },
+              "responses": {
+                "$ref": "#/definitions/responseDefinitions"
+              },
+              "security": {
+                "$ref": "#/definitions/security"
+              },
+              "securityDefinitions": {
+                "$ref": "#/definitions/securityDefinitions"
+              },
+              "tags": {
+                "type": "array",
+                "items": {
+                  "$ref": "#/definitions/tag"
+                },
+                "uniqueItems": true
+              },
+              "externalDocs": {
+                "$ref": "#/definitions/externalDocs"
+              }
+            },
+            "definitions": {
+              "info": {
+                "type": "object",
+                "description": "General information about the API.",
+                "required": [
+                  "version",
+                  "title"
+                ],
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "properties": {
+                  "title": {
+                    "type": "string",
+                    "description": "A unique and precise title of the API."
+                  },
+                  "version": {
+                    "type": "string",
+                    "description": "A semantic version number of the API."
+                  },
+                  "description": {
+                    "type": "string",
+                    "description": "A longer description of the API. Should be different from the title.  GitHub Flavored Markdown is allowed."
+                  },
+                  "termsOfService": {
+                    "type": "string",
+                    "description": "The terms of service for the API."
+                  },
+                  "contact": {
+                    "$ref": "#/definitions/contact"
+                  },
+                  "license": {
+                    "$ref": "#/definitions/license"
+                  }
+                }
+              },
+              "contact": {
+                "type": "object",
+                "description": "Contact information for the owners of the API.",
+                "additionalProperties": false,
+                "properties": {
+                  "name": {
+                    "type": "string",
+                    "description": "The identifying name of the contact person/organization."
+                  },
+                  "url": {
+                    "type": "string",
+                    "description": "The URL pointing to the contact information.",
+                    "format": "uri"
+                  },
+                  "email": {
+                    "type": "string",
+                    "description": "The email address of the contact person/organization.",
+                    "format": "email"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "license": {
+                "type": "object",
+                "required": [
+                  "name"
+                ],
+                "additionalProperties": false,
+                "properties": {
+                  "name": {
+                    "type": "string",
+                    "description": "The name of the license type. It's encouraged to use an OSI compatible license."
+                  },
+                  "url": {
+                    "type": "string",
+                    "description": "The URL pointing to the license.",
+                    "format": "uri"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "paths": {
+                "type": "object",
+                "description": "Relative paths to the individual endpoints. They must be relative to the 'basePath'.",
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  },
+                  "^/": {
+                    "$ref": "#/definitions/pathItem"
+                  }
+                },
+                "additionalProperties": false
+              },
+              "definitions": {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/definitions/schema"
+                },
+                "description": "One or more JSON objects describing the schemas being consumed and produced by the API."
+              },
+              "parameterDefinitions": {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/definitions/parameter"
+                },
+                "description": "One or more JSON representations for parameters"
+              },
+              "responseDefinitions": {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/definitions/response"
+                },
+                "description": "One or more JSON representations for responses"
+              },
+              "externalDocs": {
+                "type": "object",
+                "additionalProperties": false,
+                "description": "information about external documentation",
+                "required": [
+                  "url"
+                ],
+                "properties": {
+                  "description": {
+                    "type": "string"
+                  },
+                  "url": {
+                    "type": "string",
+                    "format": "uri"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "examples": {
+                "type": "object",
+                "additionalProperties": true
+              },
+              "mimeType": {
+                "type": "string",
+                "description": "The MIME type of the HTTP message."
+              },
+              "operation": {
+                "type": "object",
+                "required": [
+                  "responses"
+                ],
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "properties": {
+                  "tags": {
+                    "type": "array",
+                    "items": {
+                      "type": "string"
+                    },
+                    "uniqueItems": true
+                  },
+                  "summary": {
+                    "type": "string",
+                    "description": "A brief summary of the operation."
+                  },
+                  "description": {
+                    "type": "string",
+                    "description": "A longer description of the operation, GitHub Flavored Markdown is allowed."
+                  },
+                  "externalDocs": {
+                    "$ref": "#/definitions/externalDocs"
+                  },
+                  "operationId": {
+                    "type": "string",
+                    "description": "A unique identifier of the operation."
+                  },
+                  "produces": {
+                    "description": "A list of MIME types the API can produce.",
+                    "allOf": [
+                      {
+                        "$ref": "#/definitions/mediaTypeList"
+                      }
+                    ]
+                  },
+                  "consumes": {
+                    "description": "A list of MIME types the API can consume.",
+                    "allOf": [
+                      {
+                        "$ref": "#/definitions/mediaTypeList"
+                      }
+                    ]
+                  },
+                  "parameters": {
+                    "$ref": "#/definitions/parametersList"
+                  },
+                  "responses": {
+                    "$ref": "#/definitions/responses"
+                  },
+                  "schemes": {
+                    "$ref": "#/definitions/schemesList"
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "security": {
+                    "$ref": "#/definitions/security"
+                  }
+                }
+              },
+              "pathItem": {
+                "type": "object",
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "properties": {
+                  "$ref": {
+                    "type": "string"
+                  },
+                  "get": {
+                    "$ref": "#/definitions/operation"
+                  },
+                  "put": {
+                    "$ref": "#/definitions/operation"
+                  },
+                  "post": {
+                    "$ref": "#/definitions/operation"
+                  },
+                  "delete": {
+                    "$ref": "#/definitions/operation"
+                  },
+                  "options": {
+                    "$ref": "#/definitions/operation"
+                  },
+                  "head": {
+                    "$ref": "#/definitions/operation"
+                  },
+                  "patch": {
+                    "$ref": "#/definitions/operation"
+                  },
+                  "parameters": {
+                    "$ref": "#/definitions/parametersList"
+                  }
+                }
+              },
+              "responses": {
+                "type": "object",
+                "description": "Response objects names can either be any valid HTTP status code or 'default'.",
+                "minProperties": 1,
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^([0-9]{3})$|^(default)$": {
+                    "$ref": "#/definitions/responseValue"
+                  },
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "not": {
+                  "type": "object",
+                  "additionalProperties": false,
+                  "patternProperties": {
+                    "^x-": {
+                      "$ref": "#/definitions/vendorExtension"
+                    }
+                  }
+                }
+              },
+              "responseValue": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/response"
+                  },
+                  {
+                    "$ref": "#/definitions/jsonReference"
+                  }
+                ]
+              },
+              "response": {
+                "type": "object",
+                "required": [
+                  "description"
+                ],
+                "properties": {
+                  "description": {
+                    "type": "string"
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/schema"
+                      },
+                      {
+                        "$ref": "#/definitions/fileSchema"
+                      }
+                    ]
+                  },
+                  "headers": {
+                    "$ref": "#/definitions/headers"
+                  },
+                  "examples": {
+                    "$ref": "#/definitions/examples"
+                  }
+                },
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "headers": {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/definitions/header"
+                }
+              },
+              "header": {
+                "type": "object",
+                "additionalProperties": false,
+                "required": [
+                  "type"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "string",
+                      "number",
+                      "integer",
+                      "boolean",
+                      "array"
+                    ]
+                  },
+                  "format": {
+                    "type": "string"
+                  },
+                  "items": {
+                    "$ref": "#/definitions/primitivesItems"
+                  },
+                  "collectionFormat": {
+                    "$ref": "#/definitions/collectionFormat"
+                  },
+                  "default": {
+                    "$ref": "#/definitions/default"
+                  },
+                  "maximum": {
+                    "$ref": "#/definitions/maximum"
+                  },
+                  "exclusiveMaximum": {
+                    "$ref": "#/definitions/exclusiveMaximum"
+                  },
+                  "minimum": {
+                    "$ref": "#/definitions/minimum"
+                  },
+                  "exclusiveMinimum": {
+                    "$ref": "#/definitions/exclusiveMinimum"
+                  },
+                  "maxLength": {
+                    "$ref": "#/definitions/maxLength"
+                  },
+                  "minLength": {
+                    "$ref": "#/definitions/minLength"
+                  },
+                  "pattern": {
+                    "$ref": "#/definitions/pattern"
+                  },
+                  "maxItems": {
+                    "$ref": "#/definitions/maxItems"
+                  },
+                  "minItems": {
+                    "$ref": "#/definitions/minItems"
+                  },
+                  "uniqueItems": {
+                    "$ref": "#/definitions/uniqueItems"
+                  },
+                  "enum": {
+                    "$ref": "#/definitions/enum"
+                  },
+                  "multipleOf": {
+                    "$ref": "#/definitions/multipleOf"
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "vendorExtension": {
+                "description": "Any property starting with x- is valid.",
+                "additionalProperties": true,
+                "additionalItems": true
+              },
+              "bodyParameter": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema"
+                ],
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "properties": {
+                  "description": {
+                    "type": "string",
+                    "description": "A brief description of the parameter. This could contain examples of use.  GitHub Flavored Markdown is allowed."
+                  },
+                  "name": {
+                    "type": "string",
+                    "description": "The name of the parameter."
+                  },
+                  "in": {
+                    "type": "string",
+                    "description": "Determines the location of the parameter.",
+                    "enum": [
+                      "body"
+                    ]
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "description": "Determines whether or not this parameter is required or optional.",
+                    "default": false
+                  },
+                  "schema": {
+                    "$ref": "#/definitions/schema"
+                  }
+                },
+                "additionalProperties": false
+              },
+              "headerParameterSubSchema": {
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "properties": {
+                  "required": {
+                    "type": "boolean",
+                    "description": "Determines whether or not this parameter is required or optional.",
+                    "default": false
+                  },
+                  "in": {
+                    "type": "string",
+                    "description": "Determines the location of the parameter.",
+                    "enum": [
+                      "header"
+                    ]
+                  },
+                  "description": {
+                    "type": "string",
+                    "description": "A brief description of the parameter. This could contain examples of use.  GitHub Flavored Markdown is allowed."
+                  },
+                  "name": {
+                    "type": "string",
+                    "description": "The name of the parameter."
+                  },
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "string",
+                      "number",
+                      "boolean",
+                      "integer",
+                      "array"
+                    ]
+                  },
+                  "format": {
+                    "type": "string"
+                  },
+                  "items": {
+                    "$ref": "#/definitions/primitivesItems"
+                  },
+                  "collectionFormat": {
+                    "$ref": "#/definitions/collectionFormat"
+                  },
+                  "default": {
+                    "$ref": "#/definitions/default"
+                  },
+                  "maximum": {
+                    "$ref": "#/definitions/maximum"
+                  },
+                  "exclusiveMaximum": {
+                    "$ref": "#/definitions/exclusiveMaximum"
+                  },
+                  "minimum": {
+                    "$ref": "#/definitions/minimum"
+                  },
+                  "exclusiveMinimum": {
+                    "$ref": "#/definitions/exclusiveMinimum"
+                  },
+                  "maxLength": {
+                    "$ref": "#/definitions/maxLength"
+                  },
+                  "minLength": {
+                    "$ref": "#/definitions/minLength"
+                  },
+                  "pattern": {
+                    "$ref": "#/definitions/pattern"
+                  },
+                  "maxItems": {
+                    "$ref": "#/definitions/maxItems"
+                  },
+                  "minItems": {
+                    "$ref": "#/definitions/minItems"
+                  },
+                  "uniqueItems": {
+                    "$ref": "#/definitions/uniqueItems"
+                  },
+                  "enum": {
+                    "$ref": "#/definitions/enum"
+                  },
+                  "multipleOf": {
+                    "$ref": "#/definitions/multipleOf"
+                  }
+                }
+              },
+              "queryParameterSubSchema": {
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "properties": {
+                  "required": {
+                    "type": "boolean",
+                    "description": "Determines whether or not this parameter is required or optional.",
+                    "default": false
+                  },
+                  "in": {
+                    "type": "string",
+                    "description": "Determines the location of the parameter.",
+                    "enum": [
+                      "query"
+                    ]
+                  },
+                  "description": {
+                    "type": "string",
+                    "description": "A brief description of the parameter. This could contain examples of use.  GitHub Flavored Markdown is allowed."
+                  },
+                  "name": {
+                    "type": "string",
+                    "description": "The name of the parameter."
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false,
+                    "description": "allows sending a parameter by name only or with an empty value."
+                  },
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "string",
+                      "number",
+                      "boolean",
+                      "integer",
+                      "array"
+                    ]
+                  },
+                  "format": {
+                    "type": "string"
+                  },
+                  "items": {
+                    "$ref": "#/definitions/primitivesItems"
+                  },
+                  "collectionFormat": {
+                    "$ref": "#/definitions/collectionFormatWithMulti"
+                  },
+                  "default": {
+                    "$ref": "#/definitions/default"
+                  },
+                  "maximum": {
+                    "$ref": "#/definitions/maximum"
+                  },
+                  "exclusiveMaximum": {
+                    "$ref": "#/definitions/exclusiveMaximum"
+                  },
+                  "minimum": {
+                    "$ref": "#/definitions/minimum"
+                  },
+                  "exclusiveMinimum": {
+                    "$ref": "#/definitions/exclusiveMinimum"
+                  },
+                  "maxLength": {
+                    "$ref": "#/definitions/maxLength"
+                  },
+                  "minLength": {
+                    "$ref": "#/definitions/minLength"
+                  },
+                  "pattern": {
+                    "$ref": "#/definitions/pattern"
+                  },
+                  "maxItems": {
+                    "$ref": "#/definitions/maxItems"
+                  },
+                  "minItems": {
+                    "$ref": "#/definitions/minItems"
+                  },
+                  "uniqueItems": {
+                    "$ref": "#/definitions/uniqueItems"
+                  },
+                  "enum": {
+                    "$ref": "#/definitions/enum"
+                  },
+                  "multipleOf": {
+                    "$ref": "#/definitions/multipleOf"
+                  }
+                }
+              },
+              "formDataParameterSubSchema": {
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "properties": {
+                  "required": {
+                    "type": "boolean",
+                    "description": "Determines whether or not this parameter is required or optional.",
+                    "default": false
+                  },
+                  "in": {
+                    "type": "string",
+                    "description": "Determines the location of the parameter.",
+                    "enum": [
+                      "formData"
+                    ]
+                  },
+                  "description": {
+                    "type": "string",
+                    "description": "A brief description of the parameter. This could contain examples of use.  GitHub Flavored Markdown is allowed."
+                  },
+                  "name": {
+                    "type": "string",
+                    "description": "The name of the parameter."
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false,
+                    "description": "allows sending a parameter by name only or with an empty value."
+                  },
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "string",
+                      "number",
+                      "boolean",
+                      "integer",
+                      "array",
+                      "file"
+                    ]
+                  },
+                  "format": {
+                    "type": "string"
+                  },
+                  "items": {
+                    "$ref": "#/definitions/primitivesItems"
+                  },
+                  "collectionFormat": {
+                    "$ref": "#/definitions/collectionFormatWithMulti"
+                  },
+                  "default": {
+                    "$ref": "#/definitions/default"
+                  },
+                  "maximum": {
+                    "$ref": "#/definitions/maximum"
+                  },
+                  "exclusiveMaximum": {
+                    "$ref": "#/definitions/exclusiveMaximum"
+                  },
+                  "minimum": {
+                    "$ref": "#/definitions/minimum"
+                  },
+                  "exclusiveMinimum": {
+                    "$ref": "#/definitions/exclusiveMinimum"
+                  },
+                  "maxLength": {
+                    "$ref": "#/definitions/maxLength"
+                  },
+                  "minLength": {
+                    "$ref": "#/definitions/minLength"
+                  },
+                  "pattern": {
+                    "$ref": "#/definitions/pattern"
+                  },
+                  "maxItems": {
+                    "$ref": "#/definitions/maxItems"
+                  },
+                  "minItems": {
+                    "$ref": "#/definitions/minItems"
+                  },
+                  "uniqueItems": {
+                    "$ref": "#/definitions/uniqueItems"
+                  },
+                  "enum": {
+                    "$ref": "#/definitions/enum"
+                  },
+                  "multipleOf": {
+                    "$ref": "#/definitions/multipleOf"
+                  }
+                }
+              },
+              "pathParameterSubSchema": {
+                "additionalProperties": false,
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "required": [
+                  "required"
+                ],
+                "properties": {
+                  "required": {
+                    "type": "boolean",
+                    "enum": [
+                      true
+                    ],
+                    "description": "Determines whether or not this parameter is required or optional."
+                  },
+                  "in": {
+                    "type": "string",
+                    "description": "Determines the location of the parameter.",
+                    "enum": [
+                      "path"
+                    ]
+                  },
+                  "description": {
+                    "type": "string",
+                    "description": "A brief description of the parameter. This could contain examples of use.  GitHub Flavored Markdown is allowed."
+                  },
+                  "name": {
+                    "type": "string",
+                    "description": "The name of the parameter."
+                  },
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "string",
+                      "number",
+                      "boolean",
+                      "integer",
+                      "array"
+                    ]
+                  },
+                  "format": {
+                    "type": "string"
+                  },
+                  "items": {
+                    "$ref": "#/definitions/primitivesItems"
+                  },
+                  "collectionFormat": {
+                    "$ref": "#/definitions/collectionFormat"
+                  },
+                  "default": {
+                    "$ref": "#/definitions/default"
+                  },
+                  "maximum": {
+                    "$ref": "#/definitions/maximum"
+                  },
+                  "exclusiveMaximum": {
+                    "$ref": "#/definitions/exclusiveMaximum"
+                  },
+                  "minimum": {
+                    "$ref": "#/definitions/minimum"
+                  },
+                  "exclusiveMinimum": {
+                    "$ref": "#/definitions/exclusiveMinimum"
+                  },
+                  "maxLength": {
+                    "$ref": "#/definitions/maxLength"
+                  },
+                  "minLength": {
+                    "$ref": "#/definitions/minLength"
+                  },
+                  "pattern": {
+                    "$ref": "#/definitions/pattern"
+                  },
+                  "maxItems": {
+                    "$ref": "#/definitions/maxItems"
+                  },
+                  "minItems": {
+                    "$ref": "#/definitions/minItems"
+                  },
+                  "uniqueItems": {
+                    "$ref": "#/definitions/uniqueItems"
+                  },
+                  "enum": {
+                    "$ref": "#/definitions/enum"
+                  },
+                  "multipleOf": {
+                    "$ref": "#/definitions/multipleOf"
+                  }
+                }
+              },
+              "nonBodyParameter": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "type"
+                ],
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/headerParameterSubSchema"
+                  },
+                  {
+                    "$ref": "#/definitions/formDataParameterSubSchema"
+                  },
+                  {
+                    "$ref": "#/definitions/queryParameterSubSchema"
+                  },
+                  {
+                    "$ref": "#/definitions/pathParameterSubSchema"
+                  }
+                ]
+              },
+              "parameter": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/bodyParameter"
+                  },
+                  {
+                    "$ref": "#/definitions/nonBodyParameter"
+                  }
+                ]
+              },
+              "schema": {
+                "type": "object",
+                "description": "A deterministic version of a JSON Schema object.",
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "properties": {
+                  "$ref": {
+                    "type": "string"
+                  },
+                  "format": {
+                    "type": "string"
+                  },
+                  "title": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/title"
+                  },
+                  "description": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/description"
+                  },
+                  "default": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/default"
+                  },
+                  "multipleOf": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf"
+                  },
+                  "maximum": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum"
+                  },
+                  "exclusiveMaximum": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum"
+                  },
+                  "minimum": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum"
+                  },
+                  "exclusiveMinimum": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum"
+                  },
+                  "maxLength": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+                  },
+                  "minLength": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+                  },
+                  "pattern": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern"
+                  },
+                  "maxItems": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+                  },
+                  "minItems": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+                  },
+                  "uniqueItems": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems"
+                  },
+                  "maxProperties": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+                  },
+                  "minProperties": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+                  },
+                  "required": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray"
+                  },
+                  "enum": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/enum"
+                  },
+                  "additionalProperties": {
+                    "anyOf": [
+                      {
+                        "$ref": "#/definitions/schema"
+                      },
+                      {
+                        "type": "boolean"
+                      }
+                    ],
+                    "default": {}
+                  },
+                  "type": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/type"
+                  },
+                  "items": {
+                    "anyOf": [
+                      {
+                        "$ref": "#/definitions/schema"
+                      },
+                      {
+                        "type": "array",
+                        "minItems": 1,
+                        "items": {
+                          "$ref": "#/definitions/schema"
+                        }
+                      }
+                    ],
+                    "default": {}
+                  },
+                  "allOf": {
+                    "type": "array",
+                    "minItems": 1,
+                    "items": {
+                      "$ref": "#/definitions/schema"
+                    }
+                  },
+                  "oneOf": {
+                    "type": "array",
+                    "minItems": 1,
+                    "items": {
+                      "$ref": "#/definitions/schema"
+                    }
+                  },
+                  "anyOf": {
+                    "type": "array",
+                    "minItems": 1,
+                    "items": {
+                      "$ref": "#/definitions/schema"
+                    }
+                  },
+                  "properties": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/schema"
+                    },
+                    "default": {}
+                  },
+                  "discriminator": {
+                    "type": "string"
+                  },
+                  "readOnly": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "xml": {
+                    "$ref": "#/definitions/xml"
+                  },
+                  "externalDocs": {
+                    "$ref": "#/definitions/externalDocs"
+                  },
+                  "example": {}
+                },
+                "additionalProperties": false
+              },
+              "fileSchema": {
+                "type": "object",
+                "description": "A deterministic version of a JSON Schema object.",
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                },
+                "required": [
+                  "type"
+                ],
+                "properties": {
+                  "format": {
+                    "type": "string"
+                  },
+                  "title": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/title"
+                  },
+                  "description": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/description"
+                  },
+                  "default": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/properties/default"
+                  },
+                  "required": {
+                    "$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray"
+                  },
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "file"
+                    ]
+                  },
+                  "readOnly": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "externalDocs": {
+                    "$ref": "#/definitions/externalDocs"
+                  },
+                  "example": {}
+                },
+                "additionalProperties": false
+              },
+              "primitivesItems": {
+                "type": "object",
+                "additionalProperties": false,
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "string",
+                      "number",
+                      "integer",
+                      "boolean",
+                      "array"
+                    ]
+                  },
+                  "format": {
+                    "type": "string"
+                  },
+                  "items": {
+                    "$ref": "#/definitions/primitivesItems"
+                  },
+                  "collectionFormat": {
+                    "$ref": "#/definitions/collectionFormat"
+                  },
+                  "default": {
+                    "$ref": "#/definitions/default"
+                  },
+                  "maximum": {
+                    "$ref": "#/definitions/maximum"
+                  },
+                  "exclusiveMaximum": {
+                    "$ref": "#/definitions/exclusiveMaximum"
+                  },
+                  "minimum": {
+                    "$ref": "#/definitions/minimum"
+                  },
+                  "exclusiveMinimum": {
+                    "$ref": "#/definitions/exclusiveMinimum"
+                  },
+                  "maxLength": {
+                    "$ref": "#/definitions/maxLength"
+                  },
+                  "minLength": {
+                    "$ref": "#/definitions/minLength"
+                  },
+                  "pattern": {
+                    "$ref": "#/definitions/pattern"
+                  },
+                  "maxItems": {
+                    "$ref": "#/definitions/maxItems"
+                  },
+                  "minItems": {
+                    "$ref": "#/definitions/minItems"
+                  },
+                  "uniqueItems": {
+                    "$ref": "#/definitions/uniqueItems"
+                  },
+                  "enum": {
+                    "$ref": "#/definitions/enum"
+                  },
+                  "multipleOf": {
+                    "$ref": "#/definitions/multipleOf"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "security": {
+                "type": "array",
+                "items": {
+                  "$ref": "#/definitions/securityRequirement"
+                },
+                "uniqueItems": true
+              },
+              "securityRequirement": {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "array",
+                  "items": {
+                    "type": "string"
+                  },
+                  "uniqueItems": true
+                }
+              },
+              "xml": {
+                "type": "object",
+                "additionalProperties": false,
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "namespace": {
+                    "type": "string"
+                  },
+                  "prefix": {
+                    "type": "string"
+                  },
+                  "attribute": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "wrapped": {
+                    "type": "boolean",
+                    "default": false
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "tag": {
+                "type": "object",
+                "additionalProperties": false,
+                "required": [
+                  "name"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "externalDocs": {
+                    "$ref": "#/definitions/externalDocs"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "securityDefinitions": {
+                "type": "object",
+                "additionalProperties": {
+                  "oneOf": [
+                    {
+                      "$ref": "#/definitions/basicAuthenticationSecurity"
+                    },
+                    {
+                      "$ref": "#/definitions/apiKeySecurity"
+                    },
+                    {
+                      "$ref": "#/definitions/oauth2ImplicitSecurity"
+                    },
+                    {
+                      "$ref": "#/definitions/oauth2PasswordSecurity"
+                    },
+                    {
+                      "$ref": "#/definitions/oauth2ApplicationSecurity"
+                    },
+                    {
+                      "$ref": "#/definitions/oauth2AccessCodeSecurity"
+                    }
+                  ]
+                }
+              },
+              "basicAuthenticationSecurity": {
+                "type": "object",
+                "additionalProperties": false,
+                "required": [
+                  "type"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "basic"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "apiKeySecurity": {
+                "type": "object",
+                "additionalProperties": false,
+                "required": [
+                  "type",
+                  "name",
+                  "in"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "apiKey"
+                    ]
+                  },
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "header",
+                      "query"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "oauth2ImplicitSecurity": {
+                "type": "object",
+                "additionalProperties": false,
+                "required": [
+                  "type",
+                  "flow",
+                  "authorizationUrl"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "oauth2"
+                    ]
+                  },
+                  "flow": {
+                    "type": "string",
+                    "enum": [
+                      "implicit"
+                    ]
+                  },
+                  "scopes": {
+                    "$ref": "#/definitions/oauth2Scopes"
+                  },
+                  "authorizationUrl": {
+                    "type": "string",
+                    "format": "uri"
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "oauth2PasswordSecurity": {
+                "type": "object",
+                "additionalProperties": false,
+                "required": [
+                  "type",
+                  "flow",
+                  "tokenUrl"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "oauth2"
+                    ]
+                  },
+                  "flow": {
+                    "type": "string",
+                    "enum": [
+                      "password"
+                    ]
+                  },
+                  "scopes": {
+                    "$ref": "#/definitions/oauth2Scopes"
+                  },
+                  "tokenUrl": {
+                    "type": "string",
+                    "format": "uri"
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "oauth2ApplicationSecurity": {
+                "type": "object",
+                "additionalProperties": false,
+                "required": [
+                  "type",
+                  "flow",
+                  "tokenUrl"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "oauth2"
+                    ]
+                  },
+                  "flow": {
+                    "type": "string",
+                    "enum": [
+                      "application"
+                    ]
+                  },
+                  "scopes": {
+                    "$ref": "#/definitions/oauth2Scopes"
+                  },
+                  "tokenUrl": {
+                    "type": "string",
+                    "format": "uri"
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "oauth2AccessCodeSecurity": {
+                "type": "object",
+                "additionalProperties": false,
+                "required": [
+                  "type",
+                  "flow",
+                  "authorizationUrl",
+                  "tokenUrl"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "oauth2"
+                    ]
+                  },
+                  "flow": {
+                    "type": "string",
+                    "enum": [
+                      "accessCode"
+                    ]
+                  },
+                  "scopes": {
+                    "$ref": "#/definitions/oauth2Scopes"
+                  },
+                  "authorizationUrl": {
+                    "type": "string",
+                    "format": "uri"
+                  },
+                  "tokenUrl": {
+                    "type": "string",
+                    "format": "uri"
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {
+                    "$ref": "#/definitions/vendorExtension"
+                  }
+                }
+              },
+              "oauth2Scopes": {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              "mediaTypeList": {
+                "type": "array",
+                "items": {
+                  "$ref": "#/definitions/mimeType"
+                },
+                "uniqueItems": true
+              },
+              "parametersList": {
+                "type": "array",
+                "description": "The parameters needed to send a valid API call.",
+                "additionalItems": false,
+                "items": {
+                  "oneOf": [
+                    {
+                      "$ref": "#/definitions/parameter"
+                    },
+                    {
+                      "$ref": "#/definitions/jsonReference"
+                    }
+                  ]
+                },
+                "uniqueItems": true
+              },
+              "schemesList": {
+                "type": "array",
+                "description": "The transfer protocol of the API.",
+                "items": {
+                  "type": "string",
+                  "enum": [
+                    "http",
+                    "https",
+                    "ws",
+                    "wss"
+                  ]
+                },
+                "uniqueItems": true
+              },
+              "collectionFormat": {
+                "type": "string",
+                "enum": [
+                  "csv",
+                  "ssv",
+                  "tsv",
+                  "pipes"
+                ],
+                "default": "csv"
+              },
+              "collectionFormatWithMulti": {
+                "type": "string",
+                "enum": [
+                  "csv",
+                  "ssv",
+                  "tsv",
+                  "pipes",
+                  "multi"
+                ],
+                "default": "csv"
+              },
+              "title": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/title"
+              },
+              "description": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/description"
+              },
+              "default": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/default"
+              },
+              "multipleOf": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf"
+              },
+              "maximum": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/maximum"
+              },
+              "exclusiveMaximum": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum"
+              },
+              "minimum": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/minimum"
+              },
+              "exclusiveMinimum": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum"
+              },
+              "maxLength": {
+                "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+              },
+              "minLength": {
+                "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+              },
+              "pattern": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/pattern"
+              },
+              "maxItems": {
+                "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
+              },
+              "minItems": {
+                "$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
+              },
+              "uniqueItems": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems"
+              },
+              "enum": {
+                "$ref": "http://json-schema.org/draft-04/schema#/properties/enum"
+              },
+              "jsonReference": {
+                "type": "object",
+                "required": [
+                  "$ref"
+                ],
+                "additionalProperties": false,
+                "properties": {
+                  "$ref": {
+                    "type": "string"
+                  }
+                }
+              }
+            }
+          }
+        }
+      },
+      "tags": [
+        "schema"
+      ]
+    },
+    "api-host": {
+      "summary": "OpenAPI `host` must be present and non-empty string.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "host",
+        "function": "truthy"
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "api-schemes": {
+      "summary": "OpenAPI host `schemes` must be present and non-empty array.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "schemes",
+        "function": "schema",
+        "functionOptions": {
+          "schema": {
+            "items": {
+              "type": "string"
+            },
+            "minItems": 1,
+            "type": "array"
+          }
+        }
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "host-not-example": {
+      "enabled": false,
+      "summary": "Server URL should not point at `example.com`.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "host",
+        "function": "pattern",
+        "functionOptions": {
+          "notMatch": "example.com"
+        }
+      }
+    },
+    "host-trailing-slash": {
+      "summary": "Server URL should not have a trailing slash.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "host",
+        "function": "pattern",
+        "functionOptions": {
+          "notMatch": "/$"
+        }
+      }
+    },
+    "model-description": {
+      "enabled": false,
+      "summary": "Definition `description` must be present and non-empty string.",
+      "type": "style",
+      "given": "$..definitions[*]",
+      "then": {
+        "field": "description",
+        "function": "truthy"
+      }
+    },
+    "operation-security-defined": {
+      "summary": "Operation `security` values must match a scheme defined in the `securityDefinitions` object.",
+      "type": "validation",
+      "given": "$",
+      "then": {
+        "function": "oasOpSecurityDefined",
+        "functionOptions": {
+          "schemesPath": [
+            "securityDefinitions"
+          ]
+        }
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "valid-example": {
+      "summary": "Examples must be valid against their defined schema.",
+      "message": "\"{{property}}\" property {{error}}",
+      "type": "validation",
+      "given": "$..[?(@.example)]",
+      "then": {
+        "function": "schemaPath",
+        "functionOptions": {
+          "field": "example",
+          "schemaPath": "$"
+        }
+      }
+    }
+  }
+}
diff --git a/src/rulesets/oas3/index.ts b/src/rulesets/oas3/index.ts
index 397a1c0c..6a189b79 100644
--- a/src/rulesets/oas3/index.ts
+++ b/src/rulesets/oas3/index.ts
@@ -1,106 +1,8 @@
-const merge = require('lodash/merge');
-
-import { DiagnosticSeverity } from '@stoplight/types';
-import { RuleFunction, RuleType } from '../../types';
-import { commonOasRules } from '../oas';
-import * as schema from './schemas/main.json';
+import { resolve } from 'path';
+import { readRulesFromRulesets } from '../reader';
 
 export { commonOasFunctions as oas3Functions } from '../oas';
 
-export const oas3Rules = () => {
-  return merge(commonOasRules(), {
-    // specification validation
-    'oas3-schema': {
-      message: '{{error}}',
-      type: RuleType.VALIDATION,
-      severity: DiagnosticSeverity.Error,
-      then: {
-        function: RuleFunction.SCHEMA,
-        functionOptions: {
-          schema,
-        },
-      },
-      tags: ['schema'],
-    },
-
-    // generic rules
-    'api-servers': {
-      message: 'OpenAPI `servers` must be present and non-empty array.',
-      type: RuleType.STYLE,
-      given: '$',
-      then: {
-        field: 'servers',
-        function: RuleFunction.SCHEMA,
-        functionOptions: {
-          schema: {
-            items: {
-              type: 'object',
-            },
-            minItems: 1,
-            type: 'array',
-          },
-        },
-      },
-      tags: ['api'],
-    },
-    'model-description': {
-      enabled: false,
-      message: 'Model `description` must be present and non-empty string.',
-      type: RuleType.STYLE,
-      given: '$.components.schemas[*]',
-      then: {
-        field: 'description',
-        function: RuleFunction.TRUTHY,
-      },
-    },
-    'operation-security-defined': {
-      message: 'Operation `security` values must match a scheme defined in the `components.securitySchemes` object.',
-      type: RuleType.VALIDATION,
-      given: '$',
-      then: {
-        function: 'oasOpSecurityDefined',
-        functionOptions: {
-          schemesPath: ['components', 'securitySchemes'],
-        },
-      },
-      tags: ['operation'],
-    },
-    'server-not-example.com': {
-      enabled: false,
-      message: 'Server URL should not point at `example.com`.',
-      type: RuleType.STYLE,
-      given: '$.servers[*]',
-      then: {
-        field: 'url',
-        function: RuleFunction.PATTERN,
-        functionOptions: {
-          notMatch: 'example.com',
-        },
-      },
-    },
-    'server-trailing-slash': {
-      message: 'Server URL should not have a trailing slash.',
-      type: RuleType.STYLE,
-      given: '$.servers[*]',
-      then: {
-        field: 'url',
-        function: RuleFunction.PATTERN,
-        functionOptions: {
-          notMatch: '/$',
-        },
-      },
-    },
-    'valid-example': {
-      message: '"{{property}}" property {{error}}',
-      type: RuleType.VALIDATION,
-      given: '$..[?(@.example)]',
-      then: {
-        function: RuleFunction.SCHEMAPATH,
-        functionOptions: {
-          field: 'example',
-          schemaPath: '$',
-        },
-      },
-    },
-  });
+export const rules = async () => {
+  return readRulesFromRulesets(resolve(__dirname, 'ruleset.json'));
 };
diff --git a/src/rulesets/oas3/ruleset.json b/src/rulesets/oas3/ruleset.json
new file mode 100644
index 00000000..0dea40f8
--- /dev/null
+++ b/src/rulesets/oas3/ruleset.json
@@ -0,0 +1,2405 @@
+{
+  "extends": [
+    "../oas/ruleset.json"
+  ],
+  "rules": {
+    "oas3-schema": {
+      "summary": "Validate structure of OpenAPIv3 specification.",
+      "message": "{{error}}",
+      "type": "validation",
+      "severity": 0,
+      "given": "$",
+      "then": {
+        "function": "schema",
+        "functionOptions": {
+          "schema": {
+            "type": "object",
+            "required": [
+              "openapi",
+              "info",
+              "paths"
+            ],
+            "properties": {
+              "openapi": {
+                "type": "string",
+                "pattern": "^3\\.0\\.\\d(-.+)?$"
+              },
+              "info": {
+                "$ref": "#/definitions/Info"
+              },
+              "externalDocs": {
+                "$ref": "#/definitions/ExternalDocumentation"
+              },
+              "servers": {
+                "type": "array",
+                "items": {
+                  "$ref": "#/definitions/Server"
+                }
+              },
+              "security": {
+                "type": "array",
+                "items": {
+                  "$ref": "#/definitions/SecurityRequirement"
+                }
+              },
+              "tags": {
+                "type": "array",
+                "items": {
+                  "$ref": "#/definitions/Tag"
+                }
+              },
+              "paths": {
+                "$ref": "#/definitions/Paths"
+              },
+              "components": {
+                "$ref": "#/definitions/Components"
+              }
+            },
+            "patternProperties": {
+              "^x-": {}
+            },
+            "additionalProperties": false,
+            "definitions": {
+              "Reference": {
+                "type": "object",
+                "required": [
+                  "$ref"
+                ],
+                "properties": {
+                  "$ref": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  }
+                }
+              },
+              "Info": {
+                "type": "object",
+                "required": [
+                  "title",
+                  "version"
+                ],
+                "properties": {
+                  "title": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "termsOfService": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "contact": {
+                    "$ref": "#/definitions/Contact"
+                  },
+                  "license": {
+                    "$ref": "#/definitions/License"
+                  },
+                  "version": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Contact": {
+                "type": "object",
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "url": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "email": {
+                    "type": "string",
+                    "format": "email"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "License": {
+                "type": "object",
+                "required": [
+                  "name"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "url": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Server": {
+                "type": "object",
+                "required": [
+                  "url"
+                ],
+                "properties": {
+                  "url": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "variables": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/ServerVariable"
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ServerVariable": {
+                "type": "object",
+                "required": [
+                  "default"
+                ],
+                "properties": {
+                  "enum": {
+                    "type": "array",
+                    "items": {
+                      "type": "string"
+                    }
+                  },
+                  "default": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Components": {
+                "type": "object",
+                "properties": {
+                  "schemas": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/Schema"
+                          }
+                        ]
+                      }
+                    }
+                  },
+                  "responses": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/Response"
+                          }
+                        ]
+                      }
+                    }
+                  },
+                  "parameters": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/Parameter"
+                          }
+                        ]
+                      }
+                    }
+                  },
+                  "examples": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/Example"
+                          }
+                        ]
+                      }
+                    }
+                  },
+                  "requestBodies": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/RequestBody"
+                          }
+                        ]
+                      }
+                    }
+                  },
+                  "headers": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/Header"
+                          }
+                        ]
+                      }
+                    }
+                  },
+                  "securitySchemes": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/SecurityScheme"
+                          }
+                        ]
+                      }
+                    }
+                  },
+                  "links": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/Link"
+                          }
+                        ]
+                      }
+                    }
+                  },
+                  "callbacks": {
+                    "type": "object",
+                    "patternProperties": {
+                      "^[a-zA-Z0-9\\.\\-_]+$": {
+                        "oneOf": [
+                          {
+                            "$ref": "#/definitions/Reference"
+                          },
+                          {
+                            "$ref": "#/definitions/Callback"
+                          }
+                        ]
+                      }
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Schema": {
+                "type": "object",
+                "properties": {
+                  "title": {
+                    "type": "string"
+                  },
+                  "multipleOf": {
+                    "type": "number",
+                    "minimum": 0,
+                    "exclusiveMinimum": true
+                  },
+                  "maximum": {
+                    "type": "number"
+                  },
+                  "exclusiveMaximum": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "minimum": {
+                    "type": "number"
+                  },
+                  "exclusiveMinimum": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "maxLength": {
+                    "type": "integer",
+                    "minimum": 0
+                  },
+                  "minLength": {
+                    "type": "integer",
+                    "minimum": 0,
+                    "default": 0
+                  },
+                  "pattern": {
+                    "type": "string",
+                    "format": "regex"
+                  },
+                  "maxItems": {
+                    "type": "integer",
+                    "minimum": 0
+                  },
+                  "minItems": {
+                    "type": "integer",
+                    "minimum": 0,
+                    "default": 0
+                  },
+                  "uniqueItems": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "maxProperties": {
+                    "type": "integer",
+                    "minimum": 0
+                  },
+                  "minProperties": {
+                    "type": "integer",
+                    "minimum": 0,
+                    "default": 0
+                  },
+                  "required": {
+                    "type": "array",
+                    "items": {
+                      "type": "string"
+                    },
+                    "minItems": 1,
+                    "uniqueItems": true
+                  },
+                  "enum": {
+                    "type": "array",
+                    "items": {},
+                    "minItems": 1,
+                    "uniqueItems": true
+                  },
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "array",
+                      "boolean",
+                      "integer",
+                      "number",
+                      "object",
+                      "string"
+                    ]
+                  },
+                  "not": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "allOf": {
+                    "type": "array",
+                    "items": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Schema"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  },
+                  "oneOf": {
+                    "type": "array",
+                    "items": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Schema"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  },
+                  "anyOf": {
+                    "type": "array",
+                    "items": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Schema"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  },
+                  "items": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "properties": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Schema"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  },
+                  "additionalProperties": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      },
+                      {
+                        "type": "boolean"
+                      }
+                    ],
+                    "default": true
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "format": {
+                    "type": "string"
+                  },
+                  "default": {},
+                  "nullable": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "discriminator": {
+                    "$ref": "#/definitions/Discriminator"
+                  },
+                  "readOnly": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "writeOnly": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "example": {},
+                  "externalDocs": {
+                    "$ref": "#/definitions/ExternalDocumentation"
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "xml": {
+                    "$ref": "#/definitions/XML"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Discriminator": {
+                "type": "object",
+                "required": [
+                  "propertyName"
+                ],
+                "properties": {
+                  "propertyName": {
+                    "type": "string"
+                  },
+                  "mapping": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "type": "string"
+                    }
+                  }
+                }
+              },
+              "XML": {
+                "type": "object",
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "namespace": {
+                    "type": "string",
+                    "format": "url"
+                  },
+                  "prefix": {
+                    "type": "string"
+                  },
+                  "attribute": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "wrapped": {
+                    "type": "boolean",
+                    "default": false
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Response": {
+                "type": "object",
+                "required": [
+                  "description"
+                ],
+                "properties": {
+                  "description": {
+                    "type": "string"
+                  },
+                  "headers": {
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Header"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  },
+                  "content": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/MediaType"
+                    }
+                  },
+                  "links": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Link"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "MediaType": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/MediaTypeWithExample"
+                  },
+                  {
+                    "$ref": "#/definitions/MediaTypeWithExamples"
+                  }
+                ]
+              },
+              "MediaTypeWithExample": {
+                "type": "object",
+                "properties": {
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "example": {},
+                  "encoding": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/Encoding"
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "MediaTypeWithExamples": {
+                "type": "object",
+                "required": [
+                  "examples"
+                ],
+                "properties": {
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "examples": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Example"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  },
+                  "encoding": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/Encoding"
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Example": {
+                "type": "object",
+                "properties": {
+                  "summary": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "value": {},
+                  "externalValue": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Header": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/HeaderWithSchema"
+                  },
+                  {
+                    "$ref": "#/definitions/HeaderWithContent"
+                  }
+                ]
+              },
+              "HeaderWithSchema": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/HeaderWithSchemaWithExample"
+                  },
+                  {
+                    "$ref": "#/definitions/HeaderWithSchemaWithExamples"
+                  }
+                ]
+              },
+              "HeaderWithSchemaWithExample": {
+                "type": "object",
+                "required": [
+                  "schema"
+                ],
+                "properties": {
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "simple"
+                    ],
+                    "default": "simple"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "example": {}
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "HeaderWithSchemaWithExamples": {
+                "type": "object",
+                "required": [
+                  "schema",
+                  "examples"
+                ],
+                "properties": {
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "simple"
+                    ],
+                    "default": "simple"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "examples": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Example"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "HeaderWithContent": {
+                "type": "object",
+                "required": [
+                  "content"
+                ],
+                "properties": {
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "content": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/MediaType"
+                    },
+                    "minProperties": 1,
+                    "maxProperties": 1
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Paths": {
+                "type": "object",
+                "patternProperties": {
+                  "^\\/": {
+                    "$ref": "#/definitions/PathItem"
+                  },
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "PathItem": {
+                "type": "object",
+                "properties": {
+                  "$ref": {
+                    "type": "string"
+                  },
+                  "summary": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "get": {
+                    "$ref": "#/definitions/Operation"
+                  },
+                  "put": {
+                    "$ref": "#/definitions/Operation"
+                  },
+                  "post": {
+                    "$ref": "#/definitions/Operation"
+                  },
+                  "delete": {
+                    "$ref": "#/definitions/Operation"
+                  },
+                  "options": {
+                    "$ref": "#/definitions/Operation"
+                  },
+                  "head": {
+                    "$ref": "#/definitions/Operation"
+                  },
+                  "patch": {
+                    "$ref": "#/definitions/Operation"
+                  },
+                  "trace": {
+                    "$ref": "#/definitions/Operation"
+                  },
+                  "servers": {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/Server"
+                    }
+                  },
+                  "parameters": {
+                    "type": "array",
+                    "items": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Parameter"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Operation": {
+                "type": "object",
+                "required": [
+                  "responses"
+                ],
+                "properties": {
+                  "tags": {
+                    "type": "array",
+                    "items": {
+                      "type": "string"
+                    }
+                  },
+                  "summary": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "externalDocs": {
+                    "$ref": "#/definitions/ExternalDocumentation"
+                  },
+                  "operationId": {
+                    "type": "string"
+                  },
+                  "parameters": {
+                    "type": "array",
+                    "items": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Parameter"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  },
+                  "requestBody": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/RequestBody"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "responses": {
+                    "$ref": "#/definitions/Responses"
+                  },
+                  "callbacks": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Callback"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "security": {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/SecurityRequirement"
+                    }
+                  },
+                  "servers": {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/Server"
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Responses": {
+                "type": "object",
+                "properties": {
+                  "default": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Response"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  }
+                },
+                "patternProperties": {
+                  "[1-5](?:\\d{2}|XX)": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Response"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "^x-": {}
+                },
+                "minProperties": 1,
+                "additionalProperties": false,
+                "not": {
+                  "type": "object",
+                  "patternProperties": {
+                    "^x-": {}
+                  },
+                  "additionalProperties": false
+                }
+              },
+              "SecurityRequirement": {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "array",
+                  "items": {
+                    "type": "string"
+                  }
+                }
+              },
+              "Tag": {
+                "type": "object",
+                "required": [
+                  "name"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "externalDocs": {
+                    "$ref": "#/definitions/ExternalDocumentation"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ExternalDocumentation": {
+                "type": "object",
+                "required": [
+                  "url"
+                ],
+                "properties": {
+                  "description": {
+                    "type": "string"
+                  },
+                  "url": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Parameter": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/ParameterWithSchema"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithContent"
+                  }
+                ]
+              },
+              "ParameterWithSchema": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExample"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExamples"
+                  }
+                ]
+              },
+              "ParameterWithSchemaWithExample": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExampleInPath"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExampleInQuery"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExampleInHeader"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExampleInCookie"
+                  }
+                ]
+              },
+              "ParameterWithSchemaWithExampleInPath": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema",
+                  "required"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "path"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "enum": [
+                      true
+                    ]
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "matrix",
+                      "label",
+                      "simple"
+                    ],
+                    "default": "simple"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "example": {}
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithSchemaWithExampleInQuery": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "query"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "form",
+                      "spaceDelimited",
+                      "pipeDelimited",
+                      "deepObject"
+                    ],
+                    "default": "form"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "example": {}
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithSchemaWithExampleInHeader": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "header"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "simple"
+                    ],
+                    "default": "simple"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "example": {}
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithSchemaWithExampleInCookie": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "cookie"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "form"
+                    ],
+                    "default": "form"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "example": {}
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithSchemaWithExamples": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExamplesInPath"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExamplesInQuery"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExamplesInHeader"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithSchemaWithExamplesInCookie"
+                  }
+                ]
+              },
+              "ParameterWithSchemaWithExamplesInPath": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema",
+                  "required",
+                  "examples"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "path"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "enum": [
+                      true
+                    ]
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "matrix",
+                      "label",
+                      "simple"
+                    ],
+                    "default": "simple"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "examples": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Example"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithSchemaWithExamplesInQuery": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema",
+                  "examples"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "query"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "form",
+                      "spaceDelimited",
+                      "pipeDelimited",
+                      "deepObject"
+                    ],
+                    "default": "form"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "examples": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Example"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithSchemaWithExamplesInHeader": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema",
+                  "examples"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "header"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "simple"
+                    ],
+                    "default": "simple"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "examples": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Example"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithSchemaWithExamplesInCookie": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "schema",
+                  "examples"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "cookie"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "form"
+                    ],
+                    "default": "form"
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "schema": {
+                    "oneOf": [
+                      {
+                        "$ref": "#/definitions/Schema"
+                      },
+                      {
+                        "$ref": "#/definitions/Reference"
+                      }
+                    ]
+                  },
+                  "examples": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "oneOf": [
+                        {
+                          "$ref": "#/definitions/Example"
+                        },
+                        {
+                          "$ref": "#/definitions/Reference"
+                        }
+                      ]
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithContent": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/ParameterWithContentInPath"
+                  },
+                  {
+                    "$ref": "#/definitions/ParameterWithContentNotInPath"
+                  }
+                ]
+              },
+              "ParameterWithContentInPath": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "content"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "path"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "enum": [
+                      true
+                    ]
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "content": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/MediaType"
+                    },
+                    "minProperties": 1,
+                    "maxProperties": 1
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ParameterWithContentNotInPath": {
+                "type": "object",
+                "required": [
+                  "name",
+                  "in",
+                  "content"
+                ],
+                "properties": {
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "query",
+                      "header",
+                      "cookie"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "deprecated": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "allowEmptyValue": {
+                    "type": "boolean",
+                    "default": false
+                  },
+                  "content": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/MediaType"
+                    },
+                    "minProperties": 1,
+                    "maxProperties": 1
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "RequestBody": {
+                "type": "object",
+                "required": [
+                  "content"
+                ],
+                "properties": {
+                  "description": {
+                    "type": "string"
+                  },
+                  "content": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/MediaType"
+                    }
+                  },
+                  "required": {
+                    "type": "boolean",
+                    "default": false
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "SecurityScheme": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/APIKeySecurityScheme"
+                  },
+                  {
+                    "$ref": "#/definitions/HTTPSecurityScheme"
+                  },
+                  {
+                    "$ref": "#/definitions/OAuth2SecurityScheme"
+                  },
+                  {
+                    "$ref": "#/definitions/OpenIdConnectSecurityScheme"
+                  }
+                ]
+              },
+              "APIKeySecurityScheme": {
+                "type": "object",
+                "required": [
+                  "type",
+                  "name",
+                  "in"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "apiKey"
+                    ]
+                  },
+                  "name": {
+                    "type": "string"
+                  },
+                  "in": {
+                    "type": "string",
+                    "enum": [
+                      "header",
+                      "query",
+                      "cookie"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "HTTPSecurityScheme": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/NonBearerHTTPSecurityScheme"
+                  },
+                  {
+                    "$ref": "#/definitions/BearerHTTPSecurityScheme"
+                  }
+                ]
+              },
+              "NonBearerHTTPSecurityScheme": {
+                "not": {
+                  "type": "object",
+                  "properties": {
+                    "scheme": {
+                      "type": "string",
+                      "enum": [
+                        "bearer"
+                      ]
+                    }
+                  }
+                },
+                "type": "object",
+                "required": [
+                  "scheme",
+                  "type"
+                ],
+                "properties": {
+                  "scheme": {
+                    "type": "string"
+                  },
+                  "description": {
+                    "type": "string"
+                  },
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "http"
+                    ]
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "BearerHTTPSecurityScheme": {
+                "type": "object",
+                "required": [
+                  "type",
+                  "scheme"
+                ],
+                "properties": {
+                  "scheme": {
+                    "type": "string",
+                    "enum": [
+                      "bearer"
+                    ]
+                  },
+                  "bearerFormat": {
+                    "type": "string"
+                  },
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "http"
+                    ]
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "OAuth2SecurityScheme": {
+                "type": "object",
+                "required": [
+                  "type",
+                  "flows"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "oauth2"
+                    ]
+                  },
+                  "flows": {
+                    "$ref": "#/definitions/OAuthFlows"
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "OpenIdConnectSecurityScheme": {
+                "type": "object",
+                "required": [
+                  "type",
+                  "openIdConnectUrl"
+                ],
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "openIdConnect"
+                    ]
+                  },
+                  "openIdConnectUrl": {
+                    "type": "string",
+                    "format": "url"
+                  },
+                  "description": {
+                    "type": "string"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "OAuthFlows": {
+                "type": "object",
+                "properties": {
+                  "implicit": {
+                    "$ref": "#/definitions/ImplicitOAuthFlow"
+                  },
+                  "password": {
+                    "$ref": "#/definitions/PasswordOAuthFlow"
+                  },
+                  "clientCredentials": {
+                    "$ref": "#/definitions/ClientCredentialsFlow"
+                  },
+                  "authorizationCode": {
+                    "$ref": "#/definitions/AuthorizationCodeOAuthFlow"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ImplicitOAuthFlow": {
+                "type": "object",
+                "required": [
+                  "authorizationUrl",
+                  "scopes"
+                ],
+                "properties": {
+                  "authorizationUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "refreshUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "scopes": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "type": "string"
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "PasswordOAuthFlow": {
+                "type": "object",
+                "required": [
+                  "tokenUrl"
+                ],
+                "properties": {
+                  "tokenUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "refreshUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "scopes": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "type": "string"
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "ClientCredentialsFlow": {
+                "type": "object",
+                "required": [
+                  "tokenUrl"
+                ],
+                "properties": {
+                  "tokenUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "refreshUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "scopes": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "type": "string"
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "AuthorizationCodeOAuthFlow": {
+                "type": "object",
+                "required": [
+                  "authorizationUrl",
+                  "tokenUrl"
+                ],
+                "properties": {
+                  "authorizationUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "tokenUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "refreshUrl": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "scopes": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "type": "string"
+                    }
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Link": {
+                "oneOf": [
+                  {
+                    "$ref": "#/definitions/LinkWithOperationRef"
+                  },
+                  {
+                    "$ref": "#/definitions/LinkWithOperationId"
+                  }
+                ]
+              },
+              "LinkWithOperationRef": {
+                "type": "object",
+                "properties": {
+                  "operationRef": {
+                    "type": "string",
+                    "format": "uri-reference"
+                  },
+                  "parameters": {
+                    "type": "object",
+                    "additionalProperties": {}
+                  },
+                  "requestBody": {},
+                  "description": {
+                    "type": "string"
+                  },
+                  "server": {
+                    "$ref": "#/definitions/Server"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "LinkWithOperationId": {
+                "type": "object",
+                "properties": {
+                  "operationId": {
+                    "type": "string"
+                  },
+                  "parameters": {
+                    "type": "object",
+                    "additionalProperties": {}
+                  },
+                  "requestBody": {},
+                  "description": {
+                    "type": "string"
+                  },
+                  "server": {
+                    "$ref": "#/definitions/Server"
+                  }
+                },
+                "patternProperties": {
+                  "^x-": {}
+                },
+                "additionalProperties": false
+              },
+              "Callback": {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/definitions/PathItem"
+                },
+                "patternProperties": {
+                  "^x-": {}
+                }
+              },
+              "Encoding": {
+                "type": "object",
+                "properties": {
+                  "contentType": {
+                    "type": "string"
+                  },
+                  "headers": {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/definitions/Header"
+                    }
+                  },
+                  "style": {
+                    "type": "string",
+                    "enum": [
+                      "form",
+                      "spaceDelimited",
+                      "pipeDelimited",
+                      "deepObject"
+                    ]
+                  },
+                  "explode": {
+                    "type": "boolean"
+                  },
+                  "allowReserved": {
+                    "type": "boolean",
+                    "default": false
+                  }
+                },
+                "additionalProperties": false
+              }
+            }
+          }
+        }
+      },
+      "tags": [
+        "schema"
+      ]
+    },
+    "api-servers": {
+      "summary": "OpenAPI `servers` must be present and non-empty array.",
+      "type": "style",
+      "given": "$",
+      "then": {
+        "field": "servers",
+        "function": "schema",
+        "functionOptions": {
+          "schema": {
+            "items": {
+              "type": "object"
+            },
+            "minItems": 1,
+            "type": "array"
+          }
+        }
+      },
+      "tags": [
+        "api"
+      ]
+    },
+    "model-description": {
+      "enabled": false,
+      "summary": "Model `description` must be present and non-empty string.",
+      "type": "style",
+      "given": "$.components.schemas[*]",
+      "then": {
+        "field": "description",
+        "function": "truthy"
+      }
+    },
+    "operation-security-defined": {
+      "summary": "Operation `security` values must match a scheme defined in the `components.securitySchemes` object.",
+      "type": "validation",
+      "given": "$",
+      "then": {
+        "function": "oasOpSecurityDefined",
+        "functionOptions": {
+          "schemesPath": [
+            "components",
+            "securitySchemes"
+          ]
+        }
+      },
+      "tags": [
+        "operation"
+      ]
+    },
+    "server-not-example.com": {
+      "enabled": false,
+      "summary": "Server URL should not point at `example.com`.",
+      "type": "style",
+      "given": "$.servers[*]",
+      "then": {
+        "field": "url",
+        "function": "pattern",
+        "functionOptions": {
+          "notMatch": "example.com"
+        }
+      }
+    },
+    "server-trailing-slash": {
+      "summary": "Server URL should not have a trailing slash.",
+      "type": "style",
+      "given": "$.servers[*]",
+      "then": {
+        "field": "url",
+        "function": "pattern",
+        "functionOptions": {
+          "notMatch": "/$"
+        }
+      }
+    },
+    "valid-example": {
+      "summary": "Examples must be valid against their defined schema.",
+      "message": "\"{{property}}\" property {{error}}",
+      "type": "validation",
+      "given": "$..[?(@.example)]",
+      "then": {
+        "function": "schemaPath",
+        "functionOptions": {
+          "field": "example",
+          "schemaPath": "$"
+        }
+      }
+    }
+  }
+}
diff --git a/src/rulesets/reader.ts b/src/rulesets/reader.ts
index abb2c5e7..4bd898f9 100644
--- a/src/rulesets/reader.ts
+++ b/src/rulesets/reader.ts
@@ -1,5 +1,4 @@
 import { merge } from 'lodash';
-import Lint from '../cli/commands/lint';
 import { readParsable } from '../fs/reader';
 import { RuleCollection } from '../types';
 import { IRulesetFile } from '../types/ruleset';
@@ -7,20 +6,33 @@ import { formatAjv } from './ajv';
 import { resolvePath } from './path';
 import { validateRuleset } from './validation';
 
-export async function readRulesets(command: Lint, ...files: string[]): Promise<RuleCollection> {
-  const rulesets = await Promise.all(files.map(file => readRuleset(command, file)));
+export async function readRulesFromRulesets(...files: string[]): Promise<RuleCollection> {
+  const rulesets = await Promise.all(files.map(file => readRulesFromRuleset(file)));
   return merge({}, ...rulesets);
 }
 
-async function readRuleset(command: Lint, file: string): Promise<RuleCollection> {
-  command.log(`Reading ruleset ${file}`);
+export type Logger = {
+  log: (message?: string | undefined, ...args: any[]) => void;
+  error: (
+    input: string | Error,
+    options?:
+      | {
+          code?: string | undefined;
+          exit?: number | undefined;
+        }
+      | undefined,
+  ) => never;
+};
+
+async function readRulesFromRuleset(file: string): Promise<RuleCollection> {
   const parsed = await readParsable(file, 'utf8');
   const { data: ruleset } = parsed;
   const errors = validateRuleset(ruleset);
 
   if (errors.length) {
-    command.log(formatAjv(errors));
-    command.error(`Provided ruleset '${file}' is not valid`, { exit: 1 });
+    throw {
+      messages: [formatAjv(errors), `Provided ruleset '${file}' is not valid`],
+    };
   }
 
   const extendz = (ruleset as IRulesetFile).extends;
@@ -28,7 +40,7 @@ async function readRuleset(command: Lint, file: string): Promise<RuleCollection>
   if (extendz && extendz.length) {
     extendedRules = await blendRuleCollections(
       extendz.map(extend => {
-        return readRuleset(command, resolvePath(file, extend));
+        return readRulesFromRuleset(resolvePath(file, extend));
       }),
     );
   }
diff --git a/yarn.lock b/yarn.lock
index 93b00f8a..80f1d579 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -105,7 +105,7 @@
   dependencies:
     regenerator-runtime "^0.12.0"
 
-"@babel/runtime@~7.4.4":
+"@babel/runtime@^7.4.4", "@babel/runtime@~7.4.4":
   version "7.4.4"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d"
   integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==
@@ -979,6 +979,11 @@
   resolved "https://registry.yarnpkg.com/@types/text-table/-/text-table-0.2.1.tgz#39c4d4a058a82f677392dfd09976e83d9b4c9264"
   integrity sha512-dchbFCWfVgUSWEvhOkXGS7zjm+K7jCUvGrQkAHPk2Fmslfofp4HQTH2pqnQ3Pw5GPYv0zWa2AQjKtsfZThuemQ==
 
+"@types/yaml@^1.0.2":
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/@types/yaml/-/yaml-1.0.2.tgz#bba080d64714c6ef3eaa023e235dacd2cfa3c938"
+  integrity sha512-rS1VJFjyGKNHk8H97COnPIK+oeLnc0J9G0ES63o/Ky+WlJCeaFGiGCTGhV/GEVKua7ZWIV1JIDopYUwrfvTo7A==
+
 "@types/yargs@^12.0.2", "@types/yargs@^12.0.9":
   version "12.0.10"
   resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.10.tgz#17a8ec65cd8e88f51b418ceb271af18d3137df67"
@@ -1155,6 +1160,11 @@ are-we-there-yet@~1.1.2:
     delegates "^1.0.0"
     readable-stream "^2.0.6"
 
+arg@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0"
+  integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==
+
 argparse@^1.0.7:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -2172,6 +2182,18 @@ copy-descriptor@^0.1.0:
   resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
   integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
 
+copyfiles@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.1.0.tgz#0e2a4188162d6b2f3c5adfe34e9c0bd564d23164"
+  integrity sha512-cAeDE0vL/koE9WSEGxqPpSyvU638Kgfu6wfrnj7kqp9FWa1CWsU54Coo6sdYZP4GstWa39tL/wIVJWfXcujgNA==
+  dependencies:
+    glob "^7.0.5"
+    minimatch "^3.0.3"
+    mkdirp "^0.5.1"
+    noms "0.0.0"
+    through2 "^2.0.1"
+    yargs "^11.0.0"
+
 core-js@^2.4.0, core-js@^2.5.0:
   version "2.6.5"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895"
@@ -2491,7 +2513,7 @@ diff-sequences@^24.3.0:
   resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975"
   integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==
 
-diff@^3.2.0:
+diff@^3.1.0, diff@^3.2.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
   integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
@@ -3396,7 +3418,7 @@ glob@^6.0.1:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.4:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@~7.1.4:
   version "7.1.4"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
   integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
@@ -5316,7 +5338,7 @@ make-dir@^1.0.0, make-dir@^1.3.0:
   dependencies:
     pify "^3.0.0"
 
-make-error@1.x:
+make-error@1.x, make-error@^1.1.1:
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
   integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==
@@ -5558,7 +5580,7 @@ mimic-fn@^2.0.0:
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.0.0.tgz#0913ff0b121db44ef5848242c38bbb35d44cabde"
   integrity sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==
 
-"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4:
+"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.3, minimatch@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
   integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@@ -5879,6 +5901,14 @@ nomnom@1.5.2:
     colors "0.5.x"
     underscore "1.1.x"
 
+noms@0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859"
+  integrity sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=
+  dependencies:
+    inherits "^2.0.1"
+    readable-stream "~1.0.31"
+
 "nopt@2 || 3":
   version "3.0.6"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
@@ -7037,6 +7067,16 @@ read@1, read@~1.0.1, read@~1.0.7:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
+readable-stream@~1.0.31:
+  version "1.0.34"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
+  integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "0.0.1"
+    string_decoder "~0.10.x"
+
 readable-stream@~1.1.10:
   version "1.1.14"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
@@ -8112,7 +8152,7 @@ throttleit@^1.0.0:
   resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
   integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=
 
-through2@^2.0.0, through2@^2.0.2, through2@~2.0.0:
+through2@^2.0.0, through2@^2.0.1, through2@^2.0.2, through2@~2.0.0:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
   integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
@@ -8250,6 +8290,17 @@ ts-jest@24.0.x:
     semver "^5.5"
     yargs-parser "10.x"
 
+ts-node@^8.1.0:
+  version "8.1.0"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.1.0.tgz#8c4b37036abd448577db22a061fd7a67d47e658e"
+  integrity sha512-34jpuOrxDuf+O6iW1JpgTRDFynUZ1iEqtYruBqh35gICNjN8x+LpVcPAcwzLPi9VU6mdA3ym+x233nZmZp445A==
+  dependencies:
+    arg "^4.1.0"
+    diff "^3.1.0"
+    make-error "^1.1.1"
+    source-map-support "^0.5.6"
+    yn "^3.0.0"
+
 tslib@1.9.3, tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
@@ -8832,6 +8883,13 @@ yaml-ast-parser@0.0.43:
   resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb"
   integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==
 
+yaml@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.5.1.tgz#e8201678064fbcfef6afe4122ef802573b6cade8"
+  integrity sha512-btfJvMOgVthGZSgHBMrDkLuQu4YxOycw6kwuC67cUEOKJmmNozjIa02eKvuSq7usqqqpwwCvflGTF6JcDvSudw==
+  dependencies:
+    "@babel/runtime" "^7.4.4"
+
 yargs-parser@10.x, yargs-parser@^10.0.0:
   version "10.1.0"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
@@ -8915,6 +8973,11 @@ yargs@^13.2.4:
     y18n "^4.0.0"
     yargs-parser "^13.1.0"
 
+yn@^3.0.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.0.tgz#fcbe2db63610361afcc5eb9e0ac91e976d046114"
+  integrity sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg==
+
 yup@^0.26.10:
   version "0.26.10"
   resolved "https://registry.yarnpkg.com/yup/-/yup-0.26.10.tgz#3545839663289038faf25facfc07e11fd67c0cb1"


Test patch:
diff --git a/src/__tests__/functions.test.ts b/src/__tests__/functions.test.ts
index 9ce5e90f..713659f2 100644
--- a/src/__tests__/functions.test.ts
+++ b/src/__tests__/functions.test.ts
@@ -4,6 +4,7 @@ import { IRuleResult, Rule, RuleFunction } from '../types';
 const applyRuleToObject = async (r: Rule, o: object): Promise<IRuleResult[]> => {
   const s = new Spectral();
   s.addRules({
+    // @ts-ignore
     testRule: r,
   });
   return await s.run(o);
diff --git a/src/__tests__/linter.test.ts b/src/__tests__/linter.test.ts
index a7670de1..3ade2062 100644
--- a/src/__tests__/linter.test.ts
+++ b/src/__tests__/linter.test.ts
@@ -1,10 +1,12 @@
 import { DiagnosticSeverity } from '@stoplight/types';
 import * as fs from 'fs';
 import * as path from 'path';
-
-import { oas2Functions, oas2Rules } from '../rulesets/oas2';
-import { oas3Functions, oas3Rules } from '../rulesets/oas3';
+import { oas2Functions } from '../rulesets/oas2';
+import * as oas2Ruleset from '../rulesets/oas2/ruleset.json';
+import { oas3Functions } from '../rulesets/oas3';
+import * as oas3Ruleset from '../rulesets/oas3/ruleset.json';
 import { Spectral } from '../spectral';
+import { RuleCollection } from '../types';
 
 const invalidSchema = fs.readFileSync(
   path.join(__dirname, './__fixtures__/petstore.invalid-schema.oas3.yaml'),
@@ -144,7 +146,7 @@ describe('linter', () => {
   });
 
   test('should include parser diagnostics', async () => {
-    spectral.addRules(oas2Rules());
+    spectral.addRules(oas2Ruleset.rules as RuleCollection);
     spectral.addFunctions(oas2Functions());
 
     const responses = `openapi: 2.0.0
@@ -198,7 +200,7 @@ responses:: !!foo
   });
 
   test('should merge similar ajv errors', async () => {
-    spectral.addRules(oas3Rules());
+    spectral.addRules(oas3Ruleset.rules as RuleCollection);
     spectral.addFunctions(oas3Functions());
 
     const result = await spectral.run(invalidSchema);
diff --git a/src/__tests__/spectral.test.ts b/src/__tests__/spectral.test.ts
index ac278f61..e800f962 100644
--- a/src/__tests__/spectral.test.ts
+++ b/src/__tests__/spectral.test.ts
@@ -36,6 +36,7 @@ describe('spectral', () => {
       const s = new Spectral();
 
       s.addRules({
+        // @ts-ignore
         rule1: {
           summary: '',
           given: '$',
@@ -75,6 +76,7 @@ describe('spectral', () => {
         const s = new Spectral();
 
         s.addRules({
+          // @ts-ignore
           rule1: {
             summary: '',
             given: '$',
diff --git a/src/cli/commands/__tests__/lint.test.ts b/src/cli/commands/__tests__/lint.test.ts
index 39404944..835c5d05 100644
--- a/src/cli/commands/__tests__/lint.test.ts
+++ b/src/cli/commands/__tests__/lint.test.ts
@@ -3,17 +3,20 @@ import * as fs from 'fs';
 import { resolve } from 'path';
 type SpyInstance = jest.SpyInstance;
 
-const invalidSpecPath = resolve(__dirname, '__fixtures__/openapi-3.0-no-contact.yaml');
-const validSpecPath = resolve(__dirname, '__fixtures__/openapi-3.0-valid.yaml');
+const invalidOas3SpecPath = resolve(__dirname, '__fixtures__/openapi-3.0-no-contact.yaml');
+const validOas3SpecPath = resolve(__dirname, '__fixtures__/openapi-3.0-valid.yaml');
+const oas2PetstoreSpecPath = resolve(__dirname, '../../../__tests__/__fixtures__/petstore.oas2.json');
 const validConfigPath = resolve(__dirname, '__fixtures__/config.yml');
 const outputConfigPath = resolve(__dirname, '__fixtures__/config.output.yml');
-const validCustomSpecPath = resolve(__dirname, '__fixtures__/openapi-3.0-valid-custom.yaml');
+const validCustomOas3SpecPath = resolve(__dirname, '__fixtures__/openapi-3.0-valid-custom.yaml');
 const invalidRulesetPath = resolve(__dirname, '__fixtures__/ruleset-invalid.yaml');
 const validRulesetPath = resolve(__dirname, '__fixtures__/ruleset-valid.yaml');
 const validNestedRulesetPath = resolve(__dirname, '__fixtures__/ruleset-extends-valid.yaml');
 const invalidNestedRulesetPath = resolve(__dirname, '__fixtures__/ruleset-extends-invalid.yaml');
 const validRulesetConfigPath = resolve(__dirname, '__fixtures__/config.ruleset.yml');
 const invalidRulesetConfigPath = resolve(__dirname, '__fixtures__/config.ruleset.invalid.yml');
+const standardOas3RulesetPath = resolve(__dirname, '../../../rulesets/oas3/ruleset.json');
+const standardOas2RulesetPath = resolve(__dirname, '../../../rulesets/oas2/ruleset.json');
 
 /*
  * These tests currently do not assert stderr because it doesn't seem to be
@@ -33,14 +36,14 @@ describe('lint', () => {
     describe('and the file is expected to have no warnings', () => {
       test
         .stdout()
-        .command(['lint', validSpecPath])
+        .command(['lint', validCustomOas3SpecPath])
         .it('outputs no issues', ctx => {
           expect(ctx.stdout).toContain('No errors or warnings found!');
         });
     });
 
     describe('and the file is expected to trigger oas3 warnings', () => {
-      const args = ['lint', invalidSpecPath];
+      const args = ['lint', invalidOas3SpecPath];
 
       test
         .stdout()
@@ -101,14 +104,14 @@ describe('lint', () => {
     describe('extends feature', () => {
       test
         .stdout()
-        .command(['lint', validCustomSpecPath, '-r', validNestedRulesetPath])
+        .command(['lint', validCustomOas3SpecPath, '-r', validNestedRulesetPath])
         .it('should extend a valid relative ruleset', ctx => {
           expect(ctx.stdout).toContain('No errors or warnings found!');
         });
 
       test
         .stdout()
-        .command(['lint', validCustomSpecPath, '-r', invalidNestedRulesetPath])
+        .command(['lint', validCustomOas3SpecPath, '-r', invalidNestedRulesetPath])
         .exit(2)
         .it('should fail trying to extend an invalid relative ruleset', ctx => {
           expect(ctx.stdout).toContain("should have required property 'given'");
@@ -125,7 +128,7 @@ describe('lint', () => {
           });
         })
         .stdout()
-        .command(['lint', validCustomSpecPath, '-r', 'http://foo.local/ruleset-master.yaml'])
+        .command(['lint', validCustomOas3SpecPath, '-r', 'http://foo.local/ruleset-master.yaml'])
         .it('given remote nested ruleset should resolve', ctx => {
           expect(ctx.stdout).toContain('No errors or warnings found!');
         });
@@ -134,7 +137,7 @@ describe('lint', () => {
     describe('when multiple ruleset options provided', () => {
       test
         .stdout()
-        .command(['lint', validSpecPath, '-r', invalidRulesetPath, '-r', validRulesetPath])
+        .command(['lint', validOas3SpecPath, '-r', invalidRulesetPath, '-r', validRulesetPath])
         .exit(2)
         .it('given one is valid other is not, outputs "invalid ruleset" error', ctx => {
           expect(ctx.stdout).toContain(`/rules/rule-without-given-nor-them 	 should have required property 'given'`);
@@ -144,27 +147,18 @@ describe('lint', () => {
             `/rules/rule-with-invalid-enum/severity 	 should be equal to one of the allowed values`,
           );
         });
-
-      test
-        .stdout()
-        .command(['lint', validSpecPath, '-r', invalidRulesetPath, '-r', validRulesetPath])
-        .exit(2)
-        .it('given one is valid other is not, reads both', ctx => {
-          expect(ctx.stdout).toContain(`Reading ruleset ${invalidRulesetPath}`);
-          expect(ctx.stdout).toContain(`Reading ruleset ${validRulesetPath}`);
-        });
     });
 
     describe('when single ruleset option provided', () => {
       test
         .stdout()
-        .command(['lint', validSpecPath, '-r', 'non-existent-path'])
+        .command(['lint', validOas3SpecPath, '-r', 'non-existent-path'])
         .exit(2)
         .it('outputs "does not exist" error');
 
       test
         .stdout()
-        .command(['lint', validSpecPath, '-r', invalidRulesetPath])
+        .command(['lint', validOas3SpecPath, '-r', invalidRulesetPath])
         .exit(2)
         .it('outputs "invalid ruleset" error', ctx => {
           expect(ctx.stdout).toContain(`/rules/rule-without-given-nor-them 	 should have required property 'given'`);
@@ -177,14 +171,14 @@ describe('lint', () => {
 
       test
         .stdout()
-        .command(['lint', validCustomSpecPath, '-r', validRulesetPath])
+        .command(['lint', validCustomOas3SpecPath, '-r', validRulesetPath])
         .it('outputs no issues', ctx => {
           expect(ctx.stdout).toContain('No errors or warnings found!');
         });
 
       test
         .stdout()
-        .command(['lint', validSpecPath, '-r', validRulesetPath])
+        .command(['lint', validOas3SpecPath, '-r', validRulesetPath])
         .it('outputs warnings in default format', ctx => {
           expect(ctx.stdout).toContain('5:10  warning  info-matches-stoplight  Info must contain Stoplight');
           expect(ctx.stdout).not.toContain('Info object should contain `contact` object');
@@ -198,17 +192,44 @@ describe('lint', () => {
           }),
         )
         .stdout()
-        .command(['lint', validCustomSpecPath, '-r', 'http://foo.local/ruleset.yaml'])
+        .command(['lint', validCustomOas3SpecPath, '-r', 'http://foo.local/ruleset.yaml'])
         .it('given valid remote ruleset file, outputs no issues', ctx => {
           expect(ctx.stdout).toContain('No errors or warnings found!');
         });
     });
+
+    describe('when a standard oas3 ruleset provided through option', () => {
+      test
+        .stdout()
+        .command(['lint', invalidOas3SpecPath, '-r', standardOas3RulesetPath])
+        .it('outputs warnings in default format', ctx => {
+          expect(ctx.stdout).toContain(
+            '1:5  warning  api-servers       OpenAPI `servers` must be present and non-empty array',
+          );
+          expect(ctx.stdout).toContain('3:6  warning  info-contact      Info object should contain `contact` object');
+          expect(ctx.stdout).toContain(
+            '3:6  warning  info-description  OpenAPI object info `description` must be present and non-empty string',
+          );
+          expect(ctx.stdout).not.toContain('OpenAPI 3.x detected');
+        });
+
+      test
+        .stdout()
+        .command(['lint', oas2PetstoreSpecPath, '-r', standardOas2RulesetPath])
+        .it('outputs warnings in default format', ctx => {
+          expect(ctx.stdout).toContain(
+            '46:24  warning  operation-description   Operation `description` must be present and non-empty string',
+          );
+          expect(ctx.stdout).toContain('22 problems (0 errors, 22 warnings, 0 infos)');
+          expect(ctx.stdout).not.toContain('OpenAPI 2.x detected');
+        });
+    });
   });
 
   describe('when loading specification files from web', () => {
     test
       .nock('http://foo.local', api =>
-        api.get('/openapi').replyWithFile(200, validSpecPath, {
+        api.get('/openapi').replyWithFile(200, validOas3SpecPath, {
           'Content-Type': 'application/yaml',
         }),
       )
@@ -227,7 +248,7 @@ describe('lint', () => {
 
     test
       .nock('http://foo.local', api =>
-        api.get('/openapi').replyWithFile(200, invalidSpecPath, {
+        api.get('/openapi').replyWithFile(200, invalidOas3SpecPath, {
           'Content-Type': 'application/yaml',
         }),
       )
@@ -241,7 +262,7 @@ describe('lint', () => {
   describe('when using config file', () => {
     test
       .stdout()
-      .command(['lint', invalidSpecPath, '-c', validConfigPath])
+      .command(['lint', invalidOas3SpecPath, '-c', validConfigPath])
       .it('outputs warnings in json format', ctx => {
         expect(ctx.stdout).toContain('"Info object should contain `contact` object."');
         expect(ctx.stdout).toContain('"OpenAPI object info `description` must be present and non-empty string."');
@@ -250,7 +271,7 @@ describe('lint', () => {
 
     test
       .stdout()
-      .command(['lint', invalidSpecPath, '-c', outputConfigPath])
+      .command(['lint', invalidOas3SpecPath, '-c', outputConfigPath])
       .it('saves results to a file', () => {
         expect(fs.writeFile).toHaveBeenCalledWith(
           'results.json',
@@ -262,14 +283,14 @@ describe('lint', () => {
 
     test
       .stdout()
-      .command(['lint', validSpecPath, '-c', validRulesetConfigPath])
+      .command(['lint', validOas3SpecPath, '-c', validRulesetConfigPath])
       .it('outputs invalid ruleset error when invalid ruleset provided', ctx => {
         expect(ctx.stdout).toContain(`5:10  warning  info-matches-stoplight  Info must contain Stoplight`);
       });
 
     test
       .stdout()
-      .command(['lint', validSpecPath, '-c', invalidRulesetConfigPath])
+      .command(['lint', validOas3SpecPath, '-c', invalidRulesetConfigPath])
       .exit(2)
       .it('outputs invalid ruleset error when invalid ruleset provided', ctx => {
         expect(ctx.stdout).toContain(`/rules/rule-without-given-nor-them 	 should have required property 'given'`);
@@ -279,7 +300,7 @@ describe('lint', () => {
   describe('when using config file and command args', () => {
     test
       .stdout()
-      .command(['lint', invalidSpecPath, '-c', validConfigPath, '--max-results', '1'])
+      .command(['lint', invalidOas3SpecPath, '-c', validConfigPath, '--max-results', '1'])
       .it('setting --max-results to 1 will override config value of 5', ctx => {
         expect(ctx.stdout).toContain('"Info object should contain `contact` object."');
         expect(ctx.stdout).not.toContain('"OpenAPI object info `description` must be present and non-empty string."');
@@ -290,7 +311,7 @@ describe('lint', () => {
   describe('when not using config nor default config file', () => {
     test
       .stdout()
-      .command(['lint', invalidSpecPath])
+      .command(['lint', invalidOas3SpecPath])
       .it('outputs warnings in default format', ctx => {
         expect(ctx.stdout).toContain('3:6  warning  info-contact      Info object should contain `contact` object');
       });
@@ -305,7 +326,7 @@ describe('lint', () => {
 
     test
       .stdout()
-      .command(['lint', invalidSpecPath])
+      .command(['lint', invalidOas3SpecPath])
       .it('outputs data in format from default config file', ctx => {
         expect(ctx.stdout).toContain('"Info object should contain `contact` object."');
       });
diff --git a/src/rulesets/__tests__/reader.unit.ts b/src/rulesets/__tests__/reader.unit.ts
index 9feb9944..6dde2524 100644
--- a/src/rulesets/__tests__/reader.unit.ts
+++ b/src/rulesets/__tests__/reader.unit.ts
@@ -6,12 +6,11 @@ jest.mock('../path');
 import { Dictionary } from '@stoplight/types/basic';
 import { when } from 'jest-when';
 import { IRule } from '../..';
-import Lint from '../../cli/commands/lint';
 import { readParsable } from '../../fs/reader';
 import { IRulesetFile } from '../../types/ruleset';
 import { formatAjv } from '../ajv';
 import { resolvePath } from '../path';
-import { readRulesets } from '../reader';
+import { readRulesFromRulesets } from '../reader';
 import { validateRuleset } from '../validation';
 
 const readParsableMock: jest.Mock = readParsable as jest.Mock;
@@ -27,11 +26,6 @@ const simpleRule: IRule = {
   },
 };
 
-const command: Lint = {
-  log: jest.fn(),
-  error: jest.fn(),
-} as any;
-
 describe('reader', () => {
   afterEach(() => {
     jest.resetAllMocks();
@@ -47,7 +41,7 @@ describe('reader', () => {
       },
     });
 
-    expect(await readRulesets(command, 'flat-ruleset.yaml')).toEqual({
+    expect(await readRulesFromRulesets('flat-ruleset.yaml')).toEqual({
       'rule-1': { given: 'abc', then: { function: 'f' }, enabled: false },
     });
   });
@@ -67,7 +61,7 @@ describe('reader', () => {
       },
     });
 
-    expect(await readRulesets(command, 'flat-ruleset-a.yaml', 'flat-ruleset-b.yaml')).toEqual({
+    expect(await readRulesFromRulesets('flat-ruleset-a.yaml', 'flat-ruleset-b.yaml')).toEqual({
       'rule-1': { given: 'abc', then: { function: 'f' }, enabled: false },
       'rule-2': { given: 'abc', then: { function: 'f' }, enabled: false },
     });
@@ -93,7 +87,7 @@ describe('reader', () => {
       },
     });
 
-    expect(await readRulesets(command, 'oneParentRuleset')).toEqual({
+    expect(await readRulesFromRulesets('oneParentRuleset')).toEqual({
       'rule-1': { given: 'abc', then: { function: 'f' }, enabled: true },
     });
   });
@@ -119,7 +113,7 @@ describe('reader', () => {
       },
     });
 
-    expect(await readRulesets(command, 'oneParentRuleset')).toEqual({
+    expect(await readRulesFromRulesets('oneParentRuleset')).toEqual({
       'rule-1': { given: 'abc', then: { function: 'f' }, enabled: false },
       'rule-2': { given: 'another given', then: { function: 'b' } },
     });
@@ -168,7 +162,7 @@ describe('reader', () => {
       },
     });
 
-    expect(await readRulesets(command, 'oneParentRuleset')).toEqual({
+    expect(await readRulesFromRulesets('oneParentRuleset')).toEqual({
       'rule-1': { given: 'abc', then: { function: 'f' }, enabled: false },
       'rule-a': { given: 'given-a', then: { function: 'a' } },
       'rule-b': { given: 'given-b', then: { function: 'b' } },
@@ -176,7 +170,7 @@ describe('reader', () => {
     });
   });
 
-  it('given invalid ruleset should output errors', async () => {
+  it('given invalid ruleset should output errors', () => {
     const flatRuleset = {
       rules: {
         'rule-1': simpleRule,
@@ -190,12 +184,9 @@ describe('reader', () => {
       .calledWith(['fake errors'])
       .mockReturnValue('fake formatted message');
 
-    await readRulesets(command, 'flat-ruleset.yaml');
-
-    expect(command.log).toHaveBeenCalledTimes(2);
-    expect(command.log).toHaveBeenCalledWith('fake formatted message');
-    expect(command.error).toHaveBeenCalledTimes(1);
-    expect(command.error).toHaveBeenCalledWith(`Provided ruleset 'flat-ruleset.yaml' is not valid`, { exit: 1 });
+    return expect(readRulesFromRulesets('flat-ruleset.yaml')).rejects.toEqual({
+      messages: ['fake formatted message', "Provided ruleset 'flat-ruleset.yaml' is not valid"],
+    });
   });
 
   function givenRulesets(rulesets: Dictionary<IRulesetFile, string>) {
diff --git a/src/rulesets/oas/__tests__/contact-properties.ts b/src/rulesets/oas/__tests__/contact-properties.ts
index 4e6df28e..f8bef913 100644
--- a/src/rulesets/oas/__tests__/contact-properties.ts
+++ b/src/rulesets/oas/__tests__/contact-properties.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('contact-properties', () => {
   const s = new Spectral();
   s.addRules({
     'contact-properties': Object.assign(ruleset.rules['contact-properties'], {
       enabled: true,
+      type: RuleType[ruleset.rules['contact-properties'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/example-value-or-externalValue.ts b/src/rulesets/oas/__tests__/example-value-or-externalValue.ts
index b34c0c2b..286f9673 100644
--- a/src/rulesets/oas/__tests__/example-value-or-externalValue.ts
+++ b/src/rulesets/oas/__tests__/example-value-or-externalValue.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('example-value-or-externalValue', () => {
   const s = new Spectral();
   s.addRules({
     'example-value-or-externalValue': Object.assign(ruleset.rules['example-value-or-externalValue'], {
       enabled: true,
+      type: RuleType[ruleset.rules['example-value-or-externalValue'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/info-contact.ts b/src/rulesets/oas/__tests__/info-contact.ts
index 4031ddfc..b73e75a8 100644
--- a/src/rulesets/oas/__tests__/info-contact.ts
+++ b/src/rulesets/oas/__tests__/info-contact.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('info-contact', () => {
   const s = new Spectral();
   s.addRules({
     'info-contact': Object.assign(ruleset.rules['info-contact'], {
       enabled: true,
+      type: RuleType[ruleset.rules['info-contact'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/info-description.ts b/src/rulesets/oas/__tests__/info-description.ts
index 344e5908..67190b59 100644
--- a/src/rulesets/oas/__tests__/info-description.ts
+++ b/src/rulesets/oas/__tests__/info-description.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('info-description', () => {
   const s = new Spectral();
   s.addRules({
     'info-description': Object.assign(ruleset.rules['info-description'], {
       enabled: true,
+      type: RuleType[ruleset.rules['info-description'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/info-license.ts b/src/rulesets/oas/__tests__/info-license.ts
index f8714b0a..20ce47c6 100644
--- a/src/rulesets/oas/__tests__/info-license.ts
+++ b/src/rulesets/oas/__tests__/info-license.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('info-license', () => {
   const s = new Spectral();
   s.addRules({
     'info-license': Object.assign(ruleset.rules['info-license'], {
       enabled: true,
+      type: RuleType[ruleset.rules['info-license'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/license-url.ts b/src/rulesets/oas/__tests__/license-url.ts
index 4bed53bf..b055fffc 100644
--- a/src/rulesets/oas/__tests__/license-url.ts
+++ b/src/rulesets/oas/__tests__/license-url.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('license-url', () => {
   const s = new Spectral();
   s.addRules({
     'license-url': Object.assign(ruleset.rules['license-url'], {
       enabled: true,
+      type: RuleType[ruleset.rules['license-url'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/no-eval-in-markdown.ts b/src/rulesets/oas/__tests__/no-eval-in-markdown.ts
index 4749ebfe..ca142d05 100644
--- a/src/rulesets/oas/__tests__/no-eval-in-markdown.ts
+++ b/src/rulesets/oas/__tests__/no-eval-in-markdown.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('no-eval-in-markdown', () => {
   const s = new Spectral();
   s.addRules({
     'no-eval-in-markdown': Object.assign(ruleset.rules['no-eval-in-markdown'], {
       enabled: true,
+      type: RuleType[ruleset.rules['no-eval-in-markdown'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/no-script-tags-in-markdown.ts b/src/rulesets/oas/__tests__/no-script-tags-in-markdown.ts
index 272f0398..3e949fac 100644
--- a/src/rulesets/oas/__tests__/no-script-tags-in-markdown.ts
+++ b/src/rulesets/oas/__tests__/no-script-tags-in-markdown.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('no-script-tags-in-markdown', () => {
   const s = new Spectral();
   s.addRules({
     'no-script-tags-in-markdown': Object.assign(ruleset.rules['no-script-tags-in-markdown'], {
       enabled: true,
+      type: RuleType[ruleset.rules['no-script-tags-in-markdown'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/only-local-references.ts b/src/rulesets/oas/__tests__/only-local-references.ts
index 030c698d..ab6e8972 100644
--- a/src/rulesets/oas/__tests__/only-local-references.ts
+++ b/src/rulesets/oas/__tests__/only-local-references.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('only-local-references', () => {
   const s = new Spectral();
   s.addRules({
     'only-local-references': Object.assign(ruleset.rules['only-local-references'], {
       enabled: true,
+      type: RuleType[ruleset.rules['only-local-references'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/openapi-tags-alphabetical.ts b/src/rulesets/oas/__tests__/openapi-tags-alphabetical.ts
index aea4e422..4c043ea7 100644
--- a/src/rulesets/oas/__tests__/openapi-tags-alphabetical.ts
+++ b/src/rulesets/oas/__tests__/openapi-tags-alphabetical.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('openapi-tags-alphabetical', () => {
   const s = new Spectral();
   s.addRules({
     'openapi-tags-alphabetical': Object.assign(ruleset.rules['openapi-tags-alphabetical'], {
       enabled: true,
+      type: RuleType[ruleset.rules['openapi-tags-alphabetical'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/openapi-tags.ts b/src/rulesets/oas/__tests__/openapi-tags.ts
index 83a8108f..c6c2c55e 100644
--- a/src/rulesets/oas/__tests__/openapi-tags.ts
+++ b/src/rulesets/oas/__tests__/openapi-tags.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('openapi-tags', () => {
   const s = new Spectral();
   s.addRules({
     'openapi-tags': Object.assign(ruleset.rules['openapi-tags'], {
       enabled: true,
+      type: RuleType[ruleset.rules['openapi-tags'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/operation-2xx-response.ts b/src/rulesets/oas/__tests__/operation-2xx-response.ts
index 198a908d..cda34c48 100644
--- a/src/rulesets/oas/__tests__/operation-2xx-response.ts
+++ b/src/rulesets/oas/__tests__/operation-2xx-response.ts
@@ -1,7 +1,7 @@
-import { commonOasFunctions, commonOasRules } from '../';
+import { commonOasFunctions } from '../';
 import { Spectral } from '../../../spectral';
+import { rules } from '../ruleset.json';
 
-const rules = commonOasRules();
 const { oasOp2xxResponse } = commonOasFunctions();
 
 describe('operation-2xx-response', () => {
@@ -11,6 +11,7 @@ describe('operation-2xx-response', () => {
     spectral = new Spectral();
     spectral.addFunctions({ oasOp2xxResponse });
     spectral.addRules({
+      // @ts-ignore
       'operation-2xx-response': rules['operation-2xx-response'],
     });
   });
diff --git a/src/rulesets/oas/__tests__/operation-default-response.ts b/src/rulesets/oas/__tests__/operation-default-response.ts
index 763b60a1..2a3ee5d0 100644
--- a/src/rulesets/oas/__tests__/operation-default-response.ts
+++ b/src/rulesets/oas/__tests__/operation-default-response.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('operation-default-response', () => {
   const s = new Spectral();
   s.addRules({
     'operation-default-response': Object.assign(ruleset.rules['operation-default-response'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-default-response'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/operation-description.ts b/src/rulesets/oas/__tests__/operation-description.ts
index e2d92781..b69932cc 100644
--- a/src/rulesets/oas/__tests__/operation-description.ts
+++ b/src/rulesets/oas/__tests__/operation-description.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('operation-description', () => {
   const s = new Spectral();
   s.addRules({
     'operation-description': Object.assign(ruleset.rules['operation-description'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-description'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/operation-operationId-valid-in-url.ts b/src/rulesets/oas/__tests__/operation-operationId-valid-in-url.ts
index 147ffc53..04a7653a 100644
--- a/src/rulesets/oas/__tests__/operation-operationId-valid-in-url.ts
+++ b/src/rulesets/oas/__tests__/operation-operationId-valid-in-url.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('operation-operationId-valid-in-url', () => {
   const s = new Spectral();
   s.addRules({
     'operation-operationId-valid-in-url': Object.assign(ruleset.rules['operation-operationId-valid-in-url'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-operationId-valid-in-url'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/operation-operationId.ts b/src/rulesets/oas/__tests__/operation-operationId.ts
index 4036e7d3..f8b75d98 100644
--- a/src/rulesets/oas/__tests__/operation-operationId.ts
+++ b/src/rulesets/oas/__tests__/operation-operationId.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('operation-operationId', () => {
   const s = new Spectral();
   s.addRules({
     'operation-operationId': Object.assign(ruleset.rules['operation-operationId'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-operationId'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/operation-singular-tag.ts b/src/rulesets/oas/__tests__/operation-singular-tag.ts
index 08dc058c..ac560df7 100644
--- a/src/rulesets/oas/__tests__/operation-singular-tag.ts
+++ b/src/rulesets/oas/__tests__/operation-singular-tag.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('operation-singular-tag', () => {
   const s = new Spectral();
   s.addRules({
     'operation-singular-tag': Object.assign(ruleset.rules['operation-singular-tag'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-singular-tag'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/operation-summary-formatted.ts b/src/rulesets/oas/__tests__/operation-summary-formatted.ts
index 9dd0716d..33de106c 100644
--- a/src/rulesets/oas/__tests__/operation-summary-formatted.ts
+++ b/src/rulesets/oas/__tests__/operation-summary-formatted.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('operation-summary-formatted', () => {
   const s = new Spectral();
   s.addRules({
     'operation-summary-formatted': Object.assign(ruleset.rules['operation-summary-formatted'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-summary-formatted'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/operation-tags.ts b/src/rulesets/oas/__tests__/operation-tags.ts
index 4659f866..bfaabfc1 100644
--- a/src/rulesets/oas/__tests__/operation-tags.ts
+++ b/src/rulesets/oas/__tests__/operation-tags.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('operation-tags', () => {
   const s = new Spectral();
   s.addRules({
     'operation-tags': Object.assign(ruleset.rules['operation-tags'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-tags'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/parameter-description.ts b/src/rulesets/oas/__tests__/parameter-description.ts
index 1b03c5b2..4386f33b 100644
--- a/src/rulesets/oas/__tests__/parameter-description.ts
+++ b/src/rulesets/oas/__tests__/parameter-description.ts
@@ -1,7 +1,5 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('parameter-description', () => {
   const s = new Spectral();
@@ -9,6 +7,7 @@ describe('parameter-description', () => {
   s.addRules({
     'parameter-description': Object.assign(ruleset.rules['parameter-description'], {
       enabled: true,
+      type: RuleType[ruleset.rules['parameter-description'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/path-declarations-must-exist.ts b/src/rulesets/oas/__tests__/path-declarations-must-exist.ts
index 24b05e53..bef8dc99 100644
--- a/src/rulesets/oas/__tests__/path-declarations-must-exist.ts
+++ b/src/rulesets/oas/__tests__/path-declarations-must-exist.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('path-declarations-must-exist', () => {
   const s = new Spectral();
   s.addRules({
     'path-declarations-must-exist': Object.assign(ruleset.rules['path-declarations-must-exist'], {
       enabled: true,
+      type: RuleType[ruleset.rules['path-declarations-must-exist'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/path-keys-no-trailing-slash.ts b/src/rulesets/oas/__tests__/path-keys-no-trailing-slash.ts
index 713bb696..f1841fdc 100644
--- a/src/rulesets/oas/__tests__/path-keys-no-trailing-slash.ts
+++ b/src/rulesets/oas/__tests__/path-keys-no-trailing-slash.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('path-keys-no-trailing-slash', () => {
   const s = new Spectral();
   s.addRules({
     'path-keys-no-trailing-slash': Object.assign(ruleset.rules['path-keys-no-trailing-slash'], {
       enabled: true,
+      type: RuleType[ruleset.rules['path-keys-no-trailing-slash'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/path-not-include-query.ts b/src/rulesets/oas/__tests__/path-not-include-query.ts
index 475e8882..229a9baf 100644
--- a/src/rulesets/oas/__tests__/path-not-include-query.ts
+++ b/src/rulesets/oas/__tests__/path-not-include-query.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('path-not-include-query', () => {
   const s = new Spectral();
   s.addRules({
     'path-not-include-query': Object.assign(ruleset.rules['path-not-include-query'], {
       enabled: true,
+      type: RuleType[ruleset.rules['path-not-include-query'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/__tests__/tag-description.ts b/src/rulesets/oas/__tests__/tag-description.ts
index 0ef1518a..06b9c643 100644
--- a/src/rulesets/oas/__tests__/tag-description.ts
+++ b/src/rulesets/oas/__tests__/tag-description.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { commonOasRules } from '../index';
-
-const ruleset = { rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('tag-description', () => {
   const s = new Spectral();
   s.addRules({
     'tag-description': Object.assign(ruleset.rules['tag-description'], {
       enabled: true,
+      type: RuleType[ruleset.rules['tag-description'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/functions/oasOp2xxResponse/__tests__/index.ts b/src/rulesets/oas/functions/oasOp2xxResponse/__tests__/index.ts
index 7c67a06d..dc13d251 100644
--- a/src/rulesets/oas/functions/oasOp2xxResponse/__tests__/index.ts
+++ b/src/rulesets/oas/functions/oasOp2xxResponse/__tests__/index.ts
@@ -1,7 +1,7 @@
-import { Spectral } from '../../../../../spectral';
-import { commonOasFunctions, commonOasRules } from '../../../../oas/index';
-
-const ruleset = { functions: commonOasFunctions(), rules: commonOasRules() };
+import { RuleType, Spectral } from '../../../../../spectral';
+import { commonOasFunctions } from '../../../../oas/index';
+import { rules } from '../../../../oas/ruleset.json';
+const ruleset = { functions: commonOasFunctions(), rules };
 
 describe('oasOp2xxResponse', () => {
   const s = new Spectral();
@@ -9,6 +9,7 @@ describe('oasOp2xxResponse', () => {
   s.addRules({
     'operation-2xx-response': Object.assign(ruleset.rules['operation-2xx-response'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-2xx-response'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/functions/oasOpFormDataConsumeCheck/__tests__/index.ts b/src/rulesets/oas/functions/oasOpFormDataConsumeCheck/__tests__/index.ts
index f3d6c3b1..fbc75be9 100644
--- a/src/rulesets/oas/functions/oasOpFormDataConsumeCheck/__tests__/index.ts
+++ b/src/rulesets/oas/functions/oasOpFormDataConsumeCheck/__tests__/index.ts
@@ -1,7 +1,9 @@
-import { Spectral } from '../../../../../index';
-import { commonOasFunctions, commonOasRules } from '../../../index';
+import { RuleType, Spectral } from '../../../../../index';
+import { commonOasFunctions } from '../../../index';
 
-const ruleset = { functions: commonOasFunctions(), rules: commonOasRules() };
+import { rules } from '../../../ruleset.json';
+
+const ruleset = { functions: commonOasFunctions(), rules };
 
 describe('oasOpFormDataConsumeCheck', () => {
   const s = new Spectral();
@@ -9,6 +11,7 @@ describe('oasOpFormDataConsumeCheck', () => {
   s.addRules({
     'operation-formData-consume-check': Object.assign(ruleset.rules['operation-formData-consume-check'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-formData-consume-check'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/functions/oasOpIdUnique/__tests__/index.ts b/src/rulesets/oas/functions/oasOpIdUnique/__tests__/index.ts
index 2c5afc14..e43ca071 100644
--- a/src/rulesets/oas/functions/oasOpIdUnique/__tests__/index.ts
+++ b/src/rulesets/oas/functions/oasOpIdUnique/__tests__/index.ts
@@ -1,7 +1,9 @@
-import { Spectral } from '../../../../../index';
-import { commonOasFunctions, commonOasRules } from '../../../index';
+import { RuleType, Spectral } from '../../../../../index';
+import { commonOasFunctions } from '../../../index';
 
-const ruleset = { functions: commonOasFunctions(), rules: commonOasRules() };
+import { rules } from '../../../ruleset.json';
+
+const ruleset = { functions: commonOasFunctions(), rules };
 
 describe('oasOpIdUnique', () => {
   const s = new Spectral();
@@ -10,6 +12,7 @@ describe('oasOpIdUnique', () => {
   s.addRules({
     'operation-operationId-unique': Object.assign(ruleset.rules['operation-operationId-unique'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-operationId-unique'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/functions/oasOpParams/__tests__/index.test.ts b/src/rulesets/oas/functions/oasOpParams/__tests__/index.test.ts
index df0ea535..c5b0e7f2 100644
--- a/src/rulesets/oas/functions/oasOpParams/__tests__/index.test.ts
+++ b/src/rulesets/oas/functions/oasOpParams/__tests__/index.test.ts
@@ -1,7 +1,9 @@
-import { Spectral } from '../../../../../index';
-import { commonOasFunctions, commonOasRules } from '../../../index';
+import { RuleType, Spectral } from '../../../../../index';
+import { commonOasFunctions } from '../../../index';
 
-const ruleset = { functions: commonOasFunctions(), rules: commonOasRules() };
+import { rules } from '../../../ruleset.json';
+
+const ruleset = { functions: commonOasFunctions(), rules };
 
 describe('oasOpParams', () => {
   const s = new Spectral();
@@ -9,6 +11,7 @@ describe('oasOpParams', () => {
   s.addRules({
     'operation-parameters': Object.assign(ruleset.rules['operation-parameters'], {
       enabled: true,
+      type: RuleType[ruleset.rules['operation-parameters'].type],
     }),
   });
 
diff --git a/src/rulesets/oas/functions/oasOpSecurityDefined/__tests__/index.ts b/src/rulesets/oas/functions/oasOpSecurityDefined/__tests__/index.ts
index 532f6b97..32fca8d6 100644
--- a/src/rulesets/oas/functions/oasOpSecurityDefined/__tests__/index.ts
+++ b/src/rulesets/oas/functions/oasOpSecurityDefined/__tests__/index.ts
@@ -1,9 +1,11 @@
-import { Spectral } from '../../../../../index';
-import { oas2Functions, oas2Rules } from '../../../../oas2/index';
-import { oas3Functions, oas3Rules } from '../../../../oas3/index';
+import { RuleType, Spectral } from '../../../../../index';
+import { oas2Functions } from '../../../../oas2/index';
+import { rules as oas2Rules } from '../../../../oas2/ruleset.json';
+import { oas3Functions } from '../../../../oas3/index';
+import { rules as oas3Rules } from '../../../../oas3/ruleset.json';
 
-const oas2Ruleset = { functions: oas2Functions(), rules: oas2Rules() };
-const oas3Ruleset = { functions: oas3Functions(), rules: oas3Rules() };
+const oas2Ruleset = { functions: oas2Functions(), rules: oas2Rules };
+const oas3Ruleset = { functions: oas3Functions(), rules: oas3Rules };
 
 describe('oasOpSecurityDefined', () => {
   describe('oas2', () => {
@@ -12,6 +14,7 @@ describe('oasOpSecurityDefined', () => {
     s.addRules({
       'operation-security-defined': Object.assign(oas2Ruleset.rules['operation-security-defined'], {
         enabled: true,
+        type: RuleType[oas2Ruleset.rules['operation-security-defined'].type],
       }),
     });
 
@@ -61,6 +64,7 @@ describe('oasOpSecurityDefined', () => {
     s.addRules({
       'operation-security-defined': Object.assign(oas3Ruleset.rules['operation-security-defined'], {
         enabled: true,
+        type: RuleType[oas3Ruleset.rules['operation-security-defined'].type],
       }),
     });
 
diff --git a/src/rulesets/oas/functions/oasPathParam/__tests__/index.test.ts b/src/rulesets/oas/functions/oasPathParam/__tests__/index.test.ts
index 222b59bc..69304ce3 100644
--- a/src/rulesets/oas/functions/oasPathParam/__tests__/index.test.ts
+++ b/src/rulesets/oas/functions/oasPathParam/__tests__/index.test.ts
@@ -1,7 +1,9 @@
-import { Spectral } from '../../../../../index';
-import { commonOasFunctions, commonOasRules } from '../../../index';
+import { RuleType, Spectral } from '../../../../../index';
+import { commonOasFunctions } from '../../../index';
 
-const ruleset = { functions: commonOasFunctions(), rules: commonOasRules() };
+import { rules } from '../../../ruleset.json';
+
+const ruleset = { functions: commonOasFunctions(), rules };
 
 describe('oasPathParam', () => {
   const s = new Spectral();
@@ -9,6 +11,7 @@ describe('oasPathParam', () => {
   s.addRules({
     'path-params': Object.assign(ruleset.rules['path-params'], {
       enabled: true,
+      type: RuleType[ruleset.rules['path-params'].type],
     }),
   });
 
diff --git a/src/rulesets/oas2/__tests__/api-host.ts b/src/rulesets/oas2/__tests__/api-host.ts
index a07ebd0b..4b559d4a 100644
--- a/src/rulesets/oas2/__tests__/api-host.ts
+++ b/src/rulesets/oas2/__tests__/api-host.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas2Rules } from '../index';
-
-const ruleset = { rules: oas2Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('api-host', () => {
   const s = new Spectral();
   s.addRules({
     'api-host': Object.assign(ruleset.rules['api-host'], {
       enabled: true,
+      type: RuleType[ruleset.rules['api-host'].type],
     }),
   });
 
diff --git a/src/rulesets/oas2/__tests__/api-schemes.ts b/src/rulesets/oas2/__tests__/api-schemes.ts
index 5c4b4a63..28b01f9c 100644
--- a/src/rulesets/oas2/__tests__/api-schemes.ts
+++ b/src/rulesets/oas2/__tests__/api-schemes.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas2Rules } from '../index';
-
-const ruleset = { rules: oas2Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('api-schemes', () => {
   const s = new Spectral();
   s.addRules({
     'api-schemes': Object.assign(ruleset.rules['api-schemes'], {
       enabled: true,
+      type: RuleType[ruleset.rules['api-schemes'].type],
     }),
   });
 
diff --git a/src/rulesets/oas2/__tests__/host-not-example.ts b/src/rulesets/oas2/__tests__/host-not-example.ts
index ba8fd7f0..25c603fa 100644
--- a/src/rulesets/oas2/__tests__/host-not-example.ts
+++ b/src/rulesets/oas2/__tests__/host-not-example.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas2Rules } from '../index';
-
-const ruleset = { rules: oas2Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('host-not-example', () => {
   const s = new Spectral();
   s.addRules({
     'host-not-example': Object.assign(ruleset.rules['host-not-example'], {
       enabled: true,
+      type: RuleType[ruleset.rules['host-not-example'].type],
     }),
   });
 
diff --git a/src/rulesets/oas2/__tests__/host-trailing-slash.ts b/src/rulesets/oas2/__tests__/host-trailing-slash.ts
index d4ae8f59..08840ec4 100644
--- a/src/rulesets/oas2/__tests__/host-trailing-slash.ts
+++ b/src/rulesets/oas2/__tests__/host-trailing-slash.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas2Rules } from '../index';
-
-const ruleset = { rules: oas2Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('host-trailing-slash', () => {
   const s = new Spectral();
   s.addRules({
     'host-trailing-slash': Object.assign(ruleset.rules['host-trailing-slash'], {
       enabled: true,
+      type: RuleType[ruleset.rules['host-trailing-slash'].type],
     }),
   });
 
diff --git a/src/rulesets/oas2/__tests__/model-description.ts b/src/rulesets/oas2/__tests__/model-description.ts
index 17633afc..3a43912a 100644
--- a/src/rulesets/oas2/__tests__/model-description.ts
+++ b/src/rulesets/oas2/__tests__/model-description.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas2Rules } from '../index';
-
-const ruleset = { rules: oas2Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('model-description', () => {
   const s = new Spectral();
   s.addRules({
     'model-description': Object.assign(ruleset.rules['model-description'], {
       enabled: true,
+      type: RuleType[ruleset.rules['model-description'].type],
     }),
   });
 
diff --git a/src/rulesets/oas2/__tests__/oas2-schema.ts b/src/rulesets/oas2/__tests__/oas2-schema.ts
index fdd871a5..414ed7fa 100644
--- a/src/rulesets/oas2/__tests__/oas2-schema.ts
+++ b/src/rulesets/oas2/__tests__/oas2-schema.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas2Rules } from '../index';
-
-const ruleset = { rules: oas2Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('oas2-schema', () => {
   const s = new Spectral();
   s.addRules({
     'oas2-schema': Object.assign(ruleset.rules['oas2-schema'], {
       enabled: true,
+      type: RuleType[ruleset.rules['oas2-schema'].type],
     }),
   });
 
diff --git a/src/rulesets/oas2/__tests__/valid-example.ts b/src/rulesets/oas2/__tests__/valid-example.ts
index d334e8e1..d2e589a3 100644
--- a/src/rulesets/oas2/__tests__/valid-example.ts
+++ b/src/rulesets/oas2/__tests__/valid-example.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas2Rules } from '../index';
-
-const ruleset = { rules: oas2Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('valid-example', () => {
   const s = new Spectral();
   s.addRules({
     'valid-example': Object.assign(ruleset.rules['valid-example'], {
       enabled: true,
+      type: RuleType[ruleset.rules['valid-example'].type],
     }),
   });
 
diff --git a/src/rulesets/oas3/__tests__/api-servers.ts b/src/rulesets/oas3/__tests__/api-servers.ts
index 69f45185..4a734537 100644
--- a/src/rulesets/oas3/__tests__/api-servers.ts
+++ b/src/rulesets/oas3/__tests__/api-servers.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas3Rules } from '../index';
-
-const ruleset = { rules: oas3Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('api-servers', () => {
   const s = new Spectral();
   s.addRules({
     'api-servers': Object.assign(ruleset.rules['api-servers'], {
       enabled: true,
+      type: RuleType[ruleset.rules['api-servers'].type],
     }),
   });
 
diff --git a/src/rulesets/oas3/__tests__/model-description.ts b/src/rulesets/oas3/__tests__/model-description.ts
index 6825f202..08bd4517 100644
--- a/src/rulesets/oas3/__tests__/model-description.ts
+++ b/src/rulesets/oas3/__tests__/model-description.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas3Rules } from '../index';
-
-const ruleset = { rules: oas3Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('model-description', () => {
   const s = new Spectral();
   s.addRules({
     'model-description': Object.assign(ruleset.rules['model-description'], {
       enabled: true,
+      type: RuleType[ruleset.rules['model-description'].type],
     }),
   });
 
diff --git a/src/rulesets/oas3/__tests__/server-not-example.ts b/src/rulesets/oas3/__tests__/server-not-example.ts
index 9b968e7c..18225697 100644
--- a/src/rulesets/oas3/__tests__/server-not-example.ts
+++ b/src/rulesets/oas3/__tests__/server-not-example.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas3Rules } from '../index';
-
-const ruleset = { rules: oas3Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('server-not-example.com', () => {
   const s = new Spectral();
   s.addRules({
     'server-not-example.com': Object.assign(ruleset.rules['server-not-example.com'], {
       enabled: true,
+      type: RuleType[ruleset.rules['server-not-example.com'].type],
     }),
   });
 
diff --git a/src/rulesets/oas3/__tests__/server-trailing-slash.ts b/src/rulesets/oas3/__tests__/server-trailing-slash.ts
index 10a0496a..312991f5 100644
--- a/src/rulesets/oas3/__tests__/server-trailing-slash.ts
+++ b/src/rulesets/oas3/__tests__/server-trailing-slash.ts
@@ -1,13 +1,12 @@
-import { Spectral } from '../../../spectral';
-import { oas3Rules } from '../index';
-
-const ruleset = { rules: oas3Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 describe('server-trailing-slash', () => {
   const s = new Spectral();
   s.addRules({
     'server-trailing-slash': Object.assign(ruleset.rules['server-trailing-slash'], {
       enabled: true,
+      type: RuleType[ruleset.rules['server-trailing-slash'].type],
     }),
   });
 
diff --git a/src/rulesets/oas3/__tests__/valid-example.ts b/src/rulesets/oas3/__tests__/valid-example.ts
index 1e4aac6d..457d5061 100644
--- a/src/rulesets/oas3/__tests__/valid-example.ts
+++ b/src/rulesets/oas3/__tests__/valid-example.ts
@@ -1,7 +1,5 @@
-import { Spectral } from '../../../spectral';
-import { oas3Rules } from '../index';
-
-const ruleset = { rules: oas3Rules() };
+import { RuleType, Spectral } from '../../../spectral';
+import * as ruleset from '../ruleset.json';
 
 // @oclif/test packages requires @types/mocha, therefore we have 2 packages coming up with similar typings
 // TS is confused and prefers the mocha ones, so we need to instrument it to pick up the Jest ones
@@ -12,6 +10,7 @@ describe('valid-example', () => {
   s.addRules({
     'valid-example': Object.assign(ruleset.rules['valid-example'], {
       enabled: true,
+      type: RuleType[ruleset.rules['valid-example'].type],
     }),
   });