|
| 1 | +# Vacuum ruleset for TMI OpenAPI validation |
| 2 | +# Extends recommended OAS rules + full OWASP ruleset |
| 3 | +# |
| 4 | +# Usage: vacuum lint docs/reference/apis/tmi-openapi.json -r vacuum-ruleset.yaml |
| 5 | +# |
| 6 | +# Requirements: |
| 7 | +# - OpenAPI 3 specific (no OpenAPI 2 rules) |
| 8 | +# - No camelCase enforcement (TMI uses snake_case per API Design Guidelines) |
| 9 | +# - Missing examples as informational only |
| 10 | +# - OWASP security rules enabled |
| 11 | +# |
| 12 | +# Rule Suppression Decisions (documented 2026-01-17): |
| 13 | +# See below for rationale on each suppressed rule. |
| 14 | + |
| 15 | +extends: [[vacuum:oas, recommended], [vacuum:owasp, all]] |
| 16 | + |
| 17 | +rules: |
| 18 | + # Disable OpenAPI 2 specific rules (OAS3 only) |
| 19 | + owasp-security-hosts-https-oas2: off |
| 20 | + |
| 21 | + # Disable camelCase enforcement - TMI uses snake_case per API Design Guidelines |
| 22 | + camel-case-properties: off |
| 23 | + |
| 24 | + # Downgrade missing examples to info severity |
| 25 | + oas3-missing-example: info |
| 26 | + oas3-valid-schema-example: info |
| 27 | + |
| 28 | + # ============================================================================ |
| 29 | + # OWASP Rule Suppressions with Rationale |
| 30 | + # ============================================================================ |
| 31 | + |
| 32 | + # owasp-integer-format: Suppress (1,618 errors) |
| 33 | + # Rationale: TMI only builds on 64-bit platforms with Go. When no format is |
| 34 | + # specified in OpenAPI, oapi-codegen generates Go's `int` type, which is |
| 35 | + # 64-bit on all supported platforms. Requiring explicit int32/int64 on every |
| 36 | + # integer field adds documentation overhead without practical value for this |
| 37 | + # project's deployment targets. |
| 38 | + owasp-integer-format: off |
| 39 | + |
| 40 | + # owasp-integer-limit: Suppress (1,606 errors) |
| 41 | + # Rationale: Requiring min/max on every integer is impractical for most APIs. |
| 42 | + # Critical fields (pagination limits, token expiry) have limits added manually. |
| 43 | + # Fields like counts, IDs, and timestamps don't benefit from arbitrary limits. |
| 44 | + owasp-integer-limit: off |
| 45 | + |
| 46 | + # description-duplication: Suppress (2,028 info) |
| 47 | + # Rationale: Duplicate descriptions are intentional reuse - rate limit headers, |
| 48 | + # error responses, and common fields are deliberately consistent across endpoints. |
| 49 | + # The spec has been standardized to use consistent wording for these duplicates. |
| 50 | + description-duplication: off |
| 51 | + |
| 52 | + # owasp-string-restricted: Suppress (100 of 132 errors) |
| 53 | + # Rationale: Many string fields are legitimately free-form (error messages, |
| 54 | + # descriptions, names, payloads). Parameters and OAuth/OIDC fields have been |
| 55 | + # fixed with appropriate patterns/enums. Remaining fields are suppressed: |
| 56 | + # - Error response messages (43) - free-form by nature |
| 57 | + # - Admin schema names/descriptions (22) - user-provided content |
| 58 | + # - Addon schema fields (12) - flexible addon metadata |
| 59 | + # - Client credential names/descriptions (6) - user-provided |
| 60 | + # - Miscellaneous labels/metadata (17) - flexible content |
| 61 | + # Note: This rule cannot be partially suppressed, so we suppress it entirely |
| 62 | + # after fixing the 32 critical fields (7 parameters + 25 OAuth/OIDC). |
| 63 | + owasp-string-restricted: off |
| 64 | + |
| 65 | + # owasp-protection-global-unsafe: Suppress (5 errors) |
| 66 | + # Rationale: OAuth2/SAML endpoints intentionally use security: [] because they |
| 67 | + # handle authentication differently (via client credentials in body, SAML assertions, |
| 68 | + # etc.). These are marked with x-public-endpoint: true. The flagged endpoints are: |
| 69 | + # - /oauth2/token - Token exchange (client credentials in body) |
| 70 | + # - /oauth2/introspect - Token introspection (client auth in body) |
| 71 | + # - /oauth2/refresh - Refresh token exchange |
| 72 | + # - /saml/acs - SAML assertion consumer service (SAML assertions) |
| 73 | + # - /saml/slo - SAML single logout |
| 74 | + owasp-protection-global-unsafe: off |
| 75 | + |
| 76 | + # owasp-string-limit: Suppress (162 errors) |
| 77 | + # Rationale: The remaining string fields without maxLength are either: |
| 78 | + # - Already constrained by format (uuid, email, date-time) |
| 79 | + # - Part of suppressed owasp-string-restricted categories (error messages, |
| 80 | + # descriptions, payloads) |
| 81 | + # - OAuth/OIDC standard fields with well-defined specifications |
| 82 | + # Adding arbitrary maxLength to these would not add meaningful security value. |
| 83 | + owasp-string-limit: off |
| 84 | + |
| 85 | + # ============================================================================ |
| 86 | + # Schema Rule Adjustments |
| 87 | + # ============================================================================ |
| 88 | + |
| 89 | + # oas-schema-check: Suppress (3 warnings) |
| 90 | + # Rationale: The discriminator warnings are for polymorphic schemas (Diagram, |
| 91 | + # DfdDiagram.cells.items, DfdDiagramInput.cells.items) where the discriminator |
| 92 | + # property is defined in the referenced schemas (Node.shape, Edge.shape) rather |
| 93 | + # than at the parent oneOf level. Vacuum requires the property at the parent |
| 94 | + # level, but adding it there causes oapi-codegen to generate duplicate types |
| 95 | + # that break compilation. The schemas work correctly at runtime - the discriminator |
| 96 | + # maps to the correct schema based on the shape value. This is a known |
| 97 | + # incompatibility between Vacuum's strict validation and oapi-codegen's code |
| 98 | + # generation requirements. |
| 99 | + oas-schema-check: off |
| 100 | + |
| 101 | + # ============================================================================ |
| 102 | + # Path and Schema Design Suppressions (documented 2026-01-17) |
| 103 | + # ============================================================================ |
| 104 | + |
| 105 | + # paths-kebab-case: Suppress (43 warnings) |
| 106 | + # Rationale: TMI uses snake_case for API paths (/threat_models, /threat_model_id) |
| 107 | + # per established project convention. Changing to kebab-case would be a breaking |
| 108 | + # API change. The snake_case convention is consistent throughout the API and |
| 109 | + # aligns with the JSON property naming convention (also snake_case). |
| 110 | + paths-kebab-case: off |
| 111 | + |
| 112 | + # owasp-constrained-additionalProperties: Suppress (10 warnings) |
| 113 | + # owasp-no-additionalProperties: Suppress (10 warnings) |
| 114 | + # Rationale: These 10 schema locations require flexible additionalProperties: |
| 115 | + # - JointJS diagram schemas (5): Cell.data, DfdDiagram...ports.groups, |
| 116 | + # DfdDiagram...connector.args, DfdDiagram...router.args, MarkupElement.attrs |
| 117 | + # JointJS library requires arbitrary properties for diagram rendering. |
| 118 | + # - Metadata fields (3): MinimalDiagramModel.metadata, MinimalCell[0].metadata, |
| 119 | + # MinimalCell[1].metadata - user-defined metadata must be extensible. |
| 120 | + # - Extensibility (2): InvokeAddonRequest.payload (addon payloads vary by addon), |
| 121 | + # Error.details.context (error context varies by error type). |
| 122 | + # Adding maxProperties constraints would break legitimate use cases. |
| 123 | + owasp-constrained-additionalProperties: off |
| 124 | + owasp-no-additionalProperties: off |
| 125 | + |
| 126 | + # owasp-define-error-responses-401: Suppress (14 warnings) |
| 127 | + # Rationale: These are public endpoints that don't require authentication and |
| 128 | + # never return 401 by design: |
| 129 | + # - OAuth discovery: /.well-known/openid-configuration, /.well-known/jwks.json, |
| 130 | + # /.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource |
| 131 | + # - OAuth flow: /oauth2/providers, /oauth2/authorize, /oauth2/token, /oauth2/introspect |
| 132 | + # - SAML flow: /saml/slo, /saml/providers, /saml/{provider}/login, /saml/{provider}/metadata |
| 133 | + # - Health check: / |
| 134 | + # These endpoints are marked with x-public-endpoint: true vendor extension. |
| 135 | + owasp-define-error-responses-401: off |
| 136 | + |
| 137 | + # circular-references: Suppress (1 warning) |
| 138 | + # Rationale: MarkupElement references itself intentionally for recursive SVG |
| 139 | + # structure (nested SVG elements like <g> containing more <g> elements). This |
| 140 | + # is valid JSON Schema and required for JointJS markup definitions. |
| 141 | + circular-references: off |
| 142 | + |
| 143 | + # no-unnecessary-combinator: Suppress (1 warning) |
| 144 | + # Rationale: Diagram.oneOf currently contains only DfdDiagram, but additional |
| 145 | + # diagram types (sequence diagrams, architecture diagrams, etc.) will be added |
| 146 | + # in future versions. The oneOf structure is intentional to support polymorphic |
| 147 | + # diagram types. |
| 148 | + no-unnecessary-combinator: off |
0 commit comments