fix(api): fail Redocly on missing 4xx and 2xx/3xx (DEV-289)

Promote operation-4xx-response and the 2xx-or-3xx success rule to error.
Drop unused 400s on health and CORS OPTIONS. Health documents 403 like the
portal. CORS stays in Flask and is not part of the employee contract.

Co-authored-by: Adam Moussa <amoussa1229@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-09-22 00:06:49 +00:00
parent 166f2de029
commit 3d80827182
No known key found for this signature in database
3 changed files with 12 additions and 13 deletions

View file

@ -1,15 +1,18 @@
# Same Redocly recommended ruleset as internal-portal (DEV-223 / DEV-289).
# Login-style redirects succeed with 302. Recommended only counts 2XX.
# Recommended operation-2xx-response does not count 302. Login-style redirects
# succeed with 302, so that rule is replaced by operation-2xx-or-3xx-response
# at error. operation-4xx-response is promoted to error so missing 4xx fails CI.
extends:
- recommended
rules:
operation-2xx-response: off
operation-4xx-response: error
rule/operation-2xx-or-3xx-response:
subject:
type: Responses
message: Operation must define a 2XX or 3XX response.
severity: warn
severity: error
assertions:
requireAny:
- "200"

View file

@ -44,7 +44,7 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/Health"
"400":
"403":
$ref: "#/components/responses/PortalError"
/roster:
@ -118,16 +118,6 @@ paths:
$ref: "#/components/responses/PortalError"
"503":
$ref: "#/components/responses/PortalError"
options:
operationId: optionsShifts
tags: [Shifts]
summary: CORS preflight
security: []
responses:
"204":
description: Empty preflight
"400":
$ref: "#/components/responses/PortalError"
/api/shifts/pick:
post:

View file

@ -131,7 +131,13 @@ def test_openapi_uses_redocly_recommended():
assert "extends:" in redocly
assert "- recommended" in redocly
assert "operation-2xx-response: off" in redocly
assert "operation-4xx-response: error" in redocly
assert "rule/operation-2xx-or-3xx-response" in redocly
assert "severity: error" in redocly
assert "optionsShifts" not in spec
health = spec.split("/api/health:", 1)[1].split("\n /", 1)[0]
assert '"403":' in health
assert '"400":' not in health
assert 'root: openapi.yaml' in redocly
assert '"openapi:lint"' in package
assert '"@redocly/cli": "2.52.1"' in package