feat: add OpenAPI linter framework with 63 rules, custom rules runtime, and config converter#133
feat: add OpenAPI linter framework with 63 rules, custom rules runtime, and config converter#133TristanSpeakEasy merged 37 commits intomainfrom
Conversation
This commit introduces a complete linting system for OpenAPI specifications with extensive rule coverage across style, semantic, and security categories. Key features: - Linter framework with configurable rules and severity levels - 63 linting rules including OWASP security best practices - CLI command for linting OpenAPI specifications - Automatic documentation generation for lint rules - Support for custom linting configurations - Comprehensive test coverage for all rules Rule categories: - Style rules: Enforce documentation and naming conventions - Semantic rules: Validate structural correctness - OWASP rules: Security best practices and vulnerability prevention The linter integrates with the existing OpenAPI parser and provides detailed error reporting with precise location information.
There was a problem hiding this comment.
Pull request overview
This PR introduces a comprehensive OpenAPI linting framework with 63 rules covering style, semantic, and security categories. The implementation includes a configurable rule system with severity levels, CLI integration via openapi lint, auto-documentation generation, and full test coverage.
Changes:
- Added linter framework with rule registry and configuration support
- Implemented 63 linting rules across style (26), semantic (11), and OWASP security (26) categories
- Introduced CLI command for OpenAPI specification validation
- Created document indexing system for efficient rule execution
- Added comprehensive test suite with 664 passing tests
Reviewed changes
Copilot reviewed 148 out of 260 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| openapi/linter/rules/owasp_auth_insecure_schemes.go | Implements security rule detecting insecure authentication schemes |
| openapi/linter/rules/owasp_array_limit.go | Enforces maxItems constraint on array schemas for security |
| openapi/linter/rules/owasp_additional_properties_constrained.go | Validates maxProperties for schemas with additionalProperties |
| openapi/linter/rules/operation_tags.go | Ensures operations have at least one tag for organization |
| openapi/linter/rules/operation_tag_defined.go | Validates operation tags are defined globally |
| openapi/linter/rules/operation_success_response.go | Checks operations define success response codes |
| openapi/linter/rules/operation_singular_tag.go | Enforces single tag per operation convention |
| openapi/linter/rules/operation_id_valid_in_url.go | Validates operationId uses URL-friendly characters |
| openapi/linter/rules/operation_id.go | Ensures operations have operationId defined |
| openapi/linter/rules/operation_error_response.go | Checks operations define 4xx error responses |
| openapi/linter/rules/operation_description.go | Validates operations have descriptions |
| openapi/linter/rules/openapi_tags.go | Ensures specification defines global tags |
| openapi/linter/rules/oas_schema_check.go | Comprehensive schema constraint validation |
| openapi/linter/rules/oas3_no_nullable.go | Flags nullable keyword usage in OpenAPI 3.1+ |
| openapi/linter/rules/oas3_example_missing.go | Checks for missing examples in schemas/parameters |
| openapi/linter/rules/oas3_api_servers.go | Validates server definitions in OpenAPI 3.x |
| openapi/linter/rules/no_verbs_in_path.go | Prevents HTTP verbs in path segments |
| openapi/linter/rules/no_script_markdown.go | Security rule preventing script tags in descriptions |
| openapi/linter/rules/no_ref_siblings.go | Validates $ref usage in OpenAPI 3.0.x |
| openapi/linter/rules/no_eval_markdown.go | Security rule preventing eval() in descriptions |
| openapi/linter/rules/no_ambiguous_paths.go | Detects ambiguous path definitions |
| openapi/linter/rules/markdown_descriptions.go | Utility for field value node extraction |
| openapi/linter/rules/license_url.go | Validates license includes URL |
| openapi/linter/rules/info_license.go | Ensures info section has license |
| openapi/linter/rules/info_description.go | Validates info section description |
| openapi/linter/rules/info_contact.go | Ensures info section has contact details |
| openapi/linter/rules/host_trailing_slash.go | Prevents trailing slashes in server URLs |
| openapi/linter/rules/host_not_example.go | Flags example.com usage in server URLs |
| openapi/linter/rules/duplicated_entry_in_enum.go | Detects duplicate enum values |
| openapi/linter/rules/description_duplication.go | Prevents identical description/summary fields |
| openapi/linter/rules/contact_properties.go | Validates complete contact information |
| openapi/links_validate_test.go | Updated test expectations for error message format |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
📊 Test Coverage ReportCurrent Coverage: Coverage Change: 📈 +.4% (improved) Coverage by Package
📋 Detailed Coverage by Function (click to expand)
Generated by GitHub Actions |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Add LocalizeNamingCustom strategy and CustomNamingFunc option to LocalizeOptions, allowing callers to provide their own filename generation logic (e.g. content-hash-based naming).
Summary
This PR introduces a complete linting system for OpenAPI specifications with extensive rule coverage across style, semantic, and security categories. It also includes a custom rules runtime for user-defined TypeScript rules and a config converter for migrating from Spectral/Vacuum/legacy formats.
Key Features
openapi lintcommand for validating specificationsopenapi spec lint convert-rulesRule Categories
Style Rules (26 rules)
Enforce documentation and naming conventions:
Semantic Rules (11 rules)
Validate structural correctness:
OWASP Security Rules (26 rules)
Security best practices and vulnerability prevention:
Implementation Details
New Packages
linter/: Core linter framework with rule registry and configurationopenapi/linter/: OpenAPI-specific linter implementationopenapi/linter/rules/: Individual rule implementationsopenapi/linter/customrules/: TypeScript custom rules runtime (goja + esbuild)openapi/linter/customrules/types/: Published TypeScript types package (@speakeasy-api/openapi-linter-types)openapi/linter/converter/: Spectral/Vacuum/Legacy config convertercmd/update-lint-docs/: Tool for auto-generating documentationfix/: Utilities for automatic fixes (future enhancement)Custom Rules Runtime
Write linter rules in TypeScript using the
@speakeasy-api/openapi-linter-typespackage:Rulebase class with typed access to the full OpenAPI document model.tsfilesConfig Converter
Migrate existing Spectral/Vacuum/legacy linter configs to the native format:
Parse()→IntermediateConfig(IR) →Generate()→lint.yaml+.tsfileslint.yamlgivenpaths to document index collectionsopenapi spec lint convert-rules <config-file>with--output,--rules-dir,--dry-run,--forceflagsLinter Features
Document Indexing: Pre-computed indexes for efficient rule execution
Version-Aware Rules: Rules can target specific OpenAPI versions
oas3-no-nullableonly applies to OpenAPI 3.1+Multiple Output Formats: JSON and text formatters for linter results
Configurable Severity: Override default severities per rule
Testing
All tests pass, including:
Documentation
Migration Notes
Test Plan
mise cigreen (fmt, mod-check, lint, examples, tests, CLI tests, build)