Skip to content

Fixes Applied to Upstream Specs

The reconciler (scripts/reconcile.py) applies four categories of fixes to upstream specs. Constraint fixes change API contracts to match observed behavior. All other fixes are metadata-only and do not alter API contracts.

These fixes adjust OpenAPI schema constraints so the spec matches what the live API actually enforces. Each fix is driven by a Discrepancy object produced during validation.

StrategyTriggerWhat It DoesContract Change
RelaxSPEC_STRICTERSpec rejects values the API accepts. Lowers minLength/minimum, raises maxLength/maximum, adds missing enum values.Yes — widens accepted values
TightenSPEC_LOOSERSpec accepts values the API rejects. Raises minLength/minimum, lowers maxLength/maximum, restricts enums to observed values.Yes — narrows accepted values
AddMISSING_CONSTRAINTAPI enforces a constraint not documented in the spec. Adds the constraint to the schema.Yes — adds new constraint
RemoveEXTRA_CONSTRAINTSpec declares a constraint the API ignores. Removes the constraint from the schema.Yes — removes constraint

The 10 OpenAPI constraint categories tested and fixed:

  • String lengthminLength, maxLength
  • Patternpattern (regex)
  • Numeric boundsminimum, maximum, exclusiveMinimum, exclusiveMaximum
  • Required fieldsrequired
  • Enum valuesenum
  • Array boundsminItems, maxItems, uniqueItems
  • Object structureadditionalProperties, properties, propertyNames
  • CompositiononeOf, anyOf, allOf
  • DependenciesdependentRequired, dependentSchemas
  • Data typestype, format

These fixes address OAS3 quality issues found by Spectral linting. They add or correct metadata without changing API behavior.

Rule: oas3-api-servers | Contract change: No

Adds the F5 XC tenant URL template to specs missing a servers block:

"servers": [{
"url": "https://{tenant}.console.ves.volterra.io",
"description": "F5 Distributed Cloud API",
"variables": {
"tenant": {
"default": "example-tenant",
"description": "Your F5 XC tenant name"
}
}
}]

The server URL and variable values come from spectral.servers in validation.yaml.

Rule: info-contact | Contract change: No

Adds contact information to info.contact for specs missing it:

"contact": {
"name": "F5 Distributed Cloud",
"url": "https://docs.cloud.f5.com",
"email": "support@f5.com"
}

Values come from spectral.contact in validation.yaml.

Rule: operation-tags | Contract change: No

Derives a tag from the URL path prefix for untagged operations. For a path like /api/config/namespaces/{namespace}/healthchecks, the tag is config (the second non-parameter segment). The tag is added to both the operation’s tags array and the spec-level tags list.

Rule: oas3-unused-component | Contract change: No

Removes component schemas from components.schemas that are not referenced anywhere in the spec. Reduces spec size without affecting any operation.

Rule: operation-operationId-unique | Contract change: No

Appends the HTTP method as a suffix (e.g., ListItems_get) when multiple operations share the same operationId. This makes each operationId unique for code generators.

Rule: oas3-valid-schema-example | Contract change: No

Removes example or default values from schemas when the value does not conform to the schema’s own constraints (wrong type, out of range, etc.). Prevents code generators from producing invalid sample payloads.

Rule: no-script-tags-in-markdown | Contract change: No

Strips <script> tags from description fields using a regex replacement. Some upstream specs contain injected script tags that break documentation renderers.

Contract change: No (documentation-only)

Every spec receives an apiKeyAuth security scheme if one is not already present. This is always injected regardless of whether Spectral flagged it.

"components": {
"securitySchemes": {
"apiKeyAuth": {
"type": "apiKey",
"in": "header",
"name": "Authorization",
"description": "F5 XC API Token (format: APIToken <token>)"
}
}
},
"security": [{ "apiKeyAuth": [] }]

The scheme definition comes from spectral.security_scheme in validation.yaml. This tells API consumers how to authenticate but does not change runtime behavior.

Contract change: No

All output JSON specs pass through a Biome-compatible array compactor (_compact_short_arrays in scripts/utils/spec_loader.py). Short arrays that fit within 120 characters are collapsed to a single line:

// Before
"enum": [
"ACTIVE",
"INACTIVE"
]
// After
"enum": ["ACTIVE", "INACTIVE"]

Arrays exceeding the line-length threshold remain multi-line.

When multiple fix strategies could apply, the reconciler uses a priority order configured in reconciliation.priority:

  1. existing — Use the existing spec constraint if it is valid
  2. discovery — Use the discovered live API behavior
  3. inferred — Infer from patterns across similar endpoints

Every fixed spec is validated with openapi-spec-validator after all fixes are applied. If validation fails, the original spec is used as a fallback and the fix is logged as an error.