feat(api): document rate limit response headers

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 15:32:01 +00:00
parent fd09309ce9
commit 1bb2f68b3f
2 changed files with 26 additions and 0 deletions

View file

@ -202,6 +202,7 @@ func operationResponses(dataSchema map[string]any) map[string]any {
"schema": envelopeSchema(nil),
},
},
"headers": rateLimitHeaders(),
},
"504": map[string]any{
"description": "Gateway timeout",
@ -233,6 +234,7 @@ func healthResponses() map[string]any {
"schema": envelopeSchema(nil),
},
},
"headers": rateLimitHeaders(),
},
"504": map[string]any{
"description": "Gateway timeout",
@ -303,6 +305,20 @@ func envelopeSchema(dataSchema map[string]any) map[string]any {
}
}
// rateLimitHeaders documents the response headers emitted when rate limiting
// rejects a request.
func rateLimitHeaders() map[string]any {
return map[string]any{
"Retry-After": map[string]any{
"description": "Seconds until the rate limit resets",
"schema": map[string]any{
"type": "integer",
"minimum": 1,
},
},
}
}
// operationID builds a stable OpenAPI operationId from the HTTP method and path.
// The generated identifier is lower snake_case and preserves path parameter names.
func operationID(method, path string, operationIDs map[string]int) string {

View file

@ -68,6 +68,11 @@ func TestSpecBuilder_Good_EmptyGroups(t *testing.T) {
if _, ok := healthResponses["504"]; !ok {
t.Fatal("expected 504 response on /health")
}
rateLimit429 := healthResponses["429"].(map[string]any)
headers := rateLimit429["headers"].(map[string]any)
if _, ok := headers["Retry-After"]; !ok {
t.Fatal("expected Retry-After header on /health 429 response")
}
// Verify system tag exists.
tags := spec["tags"].([]any)
@ -240,6 +245,11 @@ func TestSpecBuilder_Good_SecuredResponses(t *testing.T) {
if _, ok := responses["504"]; !ok {
t.Fatal("expected 504 response in secured operation")
}
rateLimit429 := responses["429"].(map[string]any)
headers := rateLimit429["headers"].(map[string]any)
if _, ok := headers["Retry-After"]; !ok {
t.Fatal("expected Retry-After header in secured operation 429 response")
}
}
func TestSpecBuilder_Good_EnvelopeWrapping(t *testing.T) {