GreyNoise Intelligence · API Governance Rules

GreyNoise Intelligence API Rules

Spectral linting rules defining API design standards and conventions for GreyNoise Intelligence.

33 Rules error 15 warn 15 info 3
View Rules File View on GitHub

Rule Categories

greynoise

Rules

error
greynoise-info-title-prefix
API title must begin with "GreyNoise".
$.info.title
error
greynoise-info-version-semver
API version must be a semver string (e.g. 3.0.0).
$.info.version
error
greynoise-info-description-required
Info description is required and must be at least 40 characters.
$.info
warn
greynoise-info-contact-required
A contact email is required (typically [email protected]).
$.info.contact
warn
greynoise-info-license-required
A license entry is required.
$.info
error
greynoise-openapi-version
OpenAPI version must be 3.0.x to match GreyNoise published specs.
$.openapi
error
greynoise-servers-defined
At least one server entry must be defined.
$.servers
error
greynoise-servers-https
All server URLs must use HTTPS.
$.servers[*].url
warn
greynoise-servers-canonical-host
Primary server URL should be https://api.greynoise.io.
$.servers[0].url
error
greynoise-paths-lowercase
Paths must be all lowercase.
$.paths.*~
error
greynoise-paths-no-trailing-slash
Paths must not end with a trailing slash.
$.paths.*~
warn
greynoise-paths-versioned
Paths should begin with /v1, /v2, /v3, or /ping (utility).
$.paths.*~
error
greynoise-operation-summary-required
Every operation must have a summary in Title Case.
$.paths.*[get,post,put,patch,delete]
warn
greynoise-operation-description-required
Every operation must have a description.
$.paths.*[get,post,put,patch,delete]
error
greynoise-operation-operationid-required
Every operation must declare an operationId.
$.paths.*[get,post,put,patch,delete]
warn
greynoise-operation-tags-required
Every operation must declare at least one tag.
$.paths.*[get,post,put,patch,delete]
warn
greynoise-tags-defined-globally
A global tags array should be defined.
$
warn
greynoise-tag-title-case
Tag names should be in Title Case (e.g. "IP Lookup", "GNQL").
$.tags[*].name
warn
greynoise-parameter-description
Every parameter must have a description.
$.paths.*[get,post,put,patch,delete].parameters[*]
warn
greynoise-parameter-name-snake-case
Parameter names should be snake_case (GreyNoise convention).
$.paths.*[get,post,put,patch,delete].parameters[*].name
error
greynoise-api-key-in-header
API key must be passed via header, never query string.
$.paths.*[get,post,put,patch,delete].parameters[?(@.name=='key' || @.name=='api_key' || @.name=='apikey')]
warn
greynoise-request-body-json
Request bodies must include application/json.
$.paths.*[post,put,patch].requestBody.content
error
greynoise-response-2xx-required
Every operation must declare at least one 2xx response.
$.paths.*[get,post,put,patch,delete].responses
info
greynoise-response-401-recommended
Authenticated operations should declare a 401 response.
$.paths.*[get,post,put,patch,delete].responses
info
greynoise-response-429-recommended
Operations should declare a 429 (rate-limit) response.
$.paths.*[get,post,put,patch,delete].responses
warn
greynoise-response-description-required
Every response must have a description.
$.paths.*[get,post,put,patch,delete].responses.*
warn
greynoise-schema-property-snake-case
Schema property names should be snake_case (GreyNoise convention).
$.components.schemas[*].properties.*~
warn
greynoise-schema-type-required
Schemas should declare a type (unless using oneOf/allOf/anyOf/$ref).
$.components.schemas[?([email protected] && [email protected] && [email protected] && !@.$ref)]
error
greynoise-security-defined-globally
A global security entry must be defined.
$
error
greynoise-security-scheme-apikey-header
The APIKeyHeaderAuth scheme must be apiKey/header named "key".
$.components.securitySchemes.APIKeyHeaderAuth
error
greynoise-get-no-request-body
GET operations must not declare a requestBody.
$.paths.*.get
warn
greynoise-delete-no-request-body
DELETE operations must not declare a requestBody.
$.paths.*.delete
info
greynoise-operation-examples-encouraged
Operations are encouraged to provide response examples for Microcks mocking.
$.paths.*[get,post,put,patch,delete].responses['200'].content.application/json

Spectral Ruleset

Raw ↑
# GreyNoise API Spectral Ruleset
# Enforces conventions observed across the GreyNoise v3 / Enterprise APIs.
extends: spectral:oas

rules:

  # ── INFO / METADATA ─────────────────────────────────────────────────
  greynoise-info-title-prefix:
    description: API title must begin with "GreyNoise".
    message: '{{description}} — title "{{value}}" should start with "GreyNoise".'
    severity: error
    given: "$.info.title"
    then:
      function: pattern
      functionOptions:
        match: "^GreyNoise"

  greynoise-info-version-semver:
    description: API version must be a semver string (e.g. 3.0.0).
    severity: error
    given: "$.info.version"
    then:
      function: pattern
      functionOptions:
        match: "^\\d+\\.\\d+\\.\\d+$"

  greynoise-info-description-required:
    description: Info description is required and must be at least 40 characters.
    severity: error
    given: "$.info"
    then:
      field: description
      function: length
      functionOptions:
        min: 40

  greynoise-info-contact-required:
    description: A contact email is required (typically [email protected]).
    severity: warn
    given: "$.info.contact"
    then:
      field: email
      function: truthy

  greynoise-info-license-required:
    description: A license entry is required.
    severity: warn
    given: "$.info"
    then:
      field: license
      function: truthy

  # ── OPENAPI VERSION ─────────────────────────────────────────────────
  greynoise-openapi-version:
    description: OpenAPI version must be 3.0.x to match GreyNoise published specs.
    severity: error
    given: "$.openapi"
    then:
      function: pattern
      functionOptions:
        match: "^3\\.0\\."

  # ── SERVERS ─────────────────────────────────────────────────────────
  greynoise-servers-defined:
    description: At least one server entry must be defined.
    severity: error
    given: "$.servers"
    then:
      function: schema
      functionOptions:
        schema:
          type: array
          minItems: 1

  greynoise-servers-https:
    description: All server URLs must use HTTPS.
    severity: error
    given: "$.servers[*].url"
    then:
      function: pattern
      functionOptions:
        match: "^https://"

  greynoise-servers-canonical-host:
    description: Primary server URL should be https://api.greynoise.io.
    severity: warn
    given: "$.servers[0].url"
    then:
      function: pattern
      functionOptions:
        match: "^https://api\\.greynoise\\.io"

  # ── PATHS — NAMING CONVENTIONS ──────────────────────────────────────
  greynoise-paths-lowercase:
    description: Paths must be all lowercase.
    severity: error
    given: "$.paths.*~"
    then:
      function: pattern
      functionOptions:
        match: "^[^A-Z]*$"

  greynoise-paths-no-trailing-slash:
    description: Paths must not end with a trailing slash.
    severity: error
    given: "$.paths.*~"
    then:
      function: pattern
      functionOptions:
        notMatch: ".+/$"

  greynoise-paths-versioned:
    description: Paths should begin with /v1, /v2, /v3, or /ping (utility).
    severity: warn
    given: "$.paths.*~"
    then:
      function: pattern
      functionOptions:
        match: "^/(v[0-9]+/|ping$)"

  # ── OPERATIONS ──────────────────────────────────────────────────────
  greynoise-operation-summary-required:
    description: Every operation must have a summary in Title Case.
    severity: error
    given: "$.paths.*[get,post,put,patch,delete]"
    then:
      field: summary
      function: truthy

  greynoise-operation-description-required:
    description: Every operation must have a description.
    severity: warn
    given: "$.paths.*[get,post,put,patch,delete]"
    then:
      field: description
      function: truthy

  greynoise-operation-operationid-required:
    description: Every operation must declare an operationId.
    severity: error
    given: "$.paths.*[get,post,put,patch,delete]"
    then:
      field: operationId
      function: truthy

  greynoise-operation-tags-required:
    description: Every operation must declare at least one tag.
    severity: warn
    given: "$.paths.*[get,post,put,patch,delete]"
    then:
      field: tags
      function: schema
      functionOptions:
        schema:
          type: array
          minItems: 1

  # ── TAGS ────────────────────────────────────────────────────────────
  greynoise-tags-defined-globally:
    description: A global tags array should be defined.
    severity: warn
    given: "$"
    then:
      field: tags
      function: truthy

  greynoise-tag-title-case:
    description: Tag names should be in Title Case (e.g. "IP Lookup", "GNQL").
    severity: warn
    given: "$.tags[*].name"
    then:
      function: pattern
      functionOptions:
        match: "^[A-Z][A-Za-z0-9 ]+$"

  # ── PARAMETERS ──────────────────────────────────────────────────────
  greynoise-parameter-description:
    description: Every parameter must have a description.
    severity: warn
    given: "$.paths.*[get,post,put,patch,delete].parameters[*]"
    then:
      field: description
      function: truthy

  greynoise-parameter-name-snake-case:
    description: Parameter names should be snake_case (GreyNoise convention).
    severity: warn
    given: "$.paths.*[get,post,put,patch,delete].parameters[*].name"
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-z0-9_]*$"

  greynoise-api-key-in-header:
    description: API key must be passed via header, never query string.
    severity: error
    given: "$.paths.*[get,post,put,patch,delete].parameters[?(@.name=='key' || @.name=='api_key' || @.name=='apikey')]"
    then:
      field: in
      function: pattern
      functionOptions:
        match: "^header$"

  # ── REQUEST BODIES ──────────────────────────────────────────────────
  greynoise-request-body-json:
    description: Request bodies must include application/json.
    severity: warn
    given: "$.paths.*[post,put,patch].requestBody.content"
    then:
      field: application/json
      function: truthy

  # ── RESPONSES ───────────────────────────────────────────────────────
  greynoise-response-2xx-required:
    description: Every operation must declare at least one 2xx response.
    severity: error
    given: "$.paths.*[get,post,put,patch,delete].responses"
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          patternProperties:
            "^2\\d\\d$":
              type: object
          minProperties: 1

  greynoise-response-401-recommended:
    description: Authenticated operations should declare a 401 response.
    severity: info
    given: "$.paths.*[get,post,put,patch,delete].responses"
    then:
      field: "401"
      function: truthy

  greynoise-response-429-recommended:
    description: Operations should declare a 429 (rate-limit) response.
    severity: info
    given: "$.paths.*[get,post,put,patch,delete].responses"
    then:
      field: "429"
      function: truthy

  greynoise-response-description-required:
    description: Every response must have a description.
    severity: warn
    given: "$.paths.*[get,post,put,patch,delete].responses.*"
    then:
      field: description
      function: truthy

  # ── SCHEMAS — PROPERTY NAMING ───────────────────────────────────────
  greynoise-schema-property-snake-case:
    description: Schema property names should be snake_case (GreyNoise convention).
    severity: warn
    given: "$.components.schemas[*].properties.*~"
    then:
      function: pattern
      functionOptions:
        match: "^[a-z][a-z0-9_]*$"

  greynoise-schema-type-required:
    description: Schemas should declare a type (unless using oneOf/allOf/anyOf/$ref).
    severity: warn
    given: "$.components.schemas[?([email protected] && [email protected] && [email protected] && !@.$ref)]"
    then:
      field: type
      function: truthy

  # ── SECURITY ────────────────────────────────────────────────────────
  greynoise-security-defined-globally:
    description: A global security entry must be defined.
    severity: error
    given: "$"
    then:
      field: security
      function: truthy

  greynoise-security-scheme-apikey-header:
    description: The APIKeyHeaderAuth scheme must be apiKey/header named "key".
    severity: error
    given: "$.components.securitySchemes.APIKeyHeaderAuth"
    then:
      function: schema
      functionOptions:
        schema:
          type: object
          required: [type, in, name]
          properties:
            type: {const: apiKey}
            in: {const: header}
            name: {const: key}

  # ── HTTP METHOD CONVENTIONS ─────────────────────────────────────────
  greynoise-get-no-request-body:
    description: GET operations must not declare a requestBody.
    severity: error
    given: "$.paths.*.get"
    then:
      field: requestBody
      function: falsy

  greynoise-delete-no-request-body:
    description: DELETE operations must not declare a requestBody.
    severity: warn
    given: "$.paths.*.delete"
    then:
      field: requestBody
      function: falsy

  # ── GENERAL QUALITY ─────────────────────────────────────────────────
  greynoise-operation-examples-encouraged:
    description: Operations are encouraged to provide response examples for Microcks mocking.
    severity: info
    given: "$.paths.*[get,post,put,patch,delete].responses['200'].content.application/json"
    then:
      function: truthy