diff --git a/docs/components/backend/analytics/openapi.json b/docs/components/backend/analytics/openapi.json index 1debe37ac..1bd5f1003 100644 --- a/docs/components/backend/analytics/openapi.json +++ b/docs/components/backend/analytics/openapi.json @@ -3209,16 +3209,6 @@ }, "description": "Metric definitions" }, - "400": { - "content": { - "application/problem+json": { - "schema": { - "$ref": "#/components/schemas/Problem" - } - } - }, - "description": "Bad Request" - }, "401": { "content": { "application/problem+json": { @@ -3229,46 +3219,6 @@ }, "description": "Unauthorized" }, - "403": { - "content": { - "application/problem+json": { - "schema": { - "$ref": "#/components/schemas/Problem" - } - } - }, - "description": "Forbidden" - }, - "404": { - "content": { - "application/problem+json": { - "schema": { - "$ref": "#/components/schemas/Problem" - } - } - }, - "description": "Not Found" - }, - "409": { - "content": { - "application/problem+json": { - "schema": { - "$ref": "#/components/schemas/Problem" - } - } - }, - "description": "Conflict" - }, - "429": { - "content": { - "application/problem+json": { - "schema": { - "$ref": "#/components/schemas/Problem" - } - } - }, - "description": "Too Many Requests" - }, "500": { "content": { "application/problem+json": { @@ -3333,16 +3283,6 @@ }, "description": "Unauthorized" }, - "403": { - "content": { - "application/problem+json": { - "schema": { - "$ref": "#/components/schemas/Problem" - } - } - }, - "description": "Forbidden" - }, "404": { "content": { "application/problem+json": { @@ -3353,7 +3293,7 @@ }, "description": "Not Found" }, - "409": { + "415": { "content": { "application/problem+json": { "schema": { @@ -3361,7 +3301,7 @@ } } }, - "description": "Conflict" + "description": "Unsupported Media Type" }, "429": { "content": { @@ -3447,17 +3387,7 @@ }, "description": "Forbidden" }, - "404": { - "content": { - "application/problem+json": { - "schema": { - "$ref": "#/components/schemas/Problem" - } - } - }, - "description": "Not Found" - }, - "409": { + "415": { "content": { "application/problem+json": { "schema": { @@ -3465,17 +3395,7 @@ } } }, - "description": "Conflict" - }, - "429": { - "content": { - "application/problem+json": { - "schema": { - "$ref": "#/components/schemas/Problem" - } - } - }, - "description": "Too Many Requests" + "description": "Unsupported Media Type" }, "500": { "content": { diff --git a/src/backend/services/analytics/src/api/mod.rs b/src/backend/services/analytics/src/api/mod.rs index f158dccfc..6d8bc9b24 100644 --- a/src/backend/services/analytics/src/api/mod.rs +++ b/src/backend/services/analytics/src/api/mod.rs @@ -235,7 +235,11 @@ fn build_operations(router: Router, openapi: &dyn OpenApiRegistry) -> Router { StatusCode::OK, "Metric results", ) - .standard_errors(openapi) + .error_400(openapi) + .error_401(openapi) + .error_403(openapi) + .error_415(openapi) + .error_500(openapi) .handler(metric_results::query_metric_results) .register(router, openapi); @@ -345,7 +349,12 @@ fn build_operations(router: Router, openapi: &dyn OpenApiRegistry) -> Router { StatusCode::OK, "Metric evidence", ) - .standard_errors(openapi) + .error_400(openapi) + .error_401(openapi) + .error_404(openapi) + .error_415(openapi) + .error_429(openapi) + .error_500(openapi) .handler(metric_drilldown::query_metric_drilldown) .register(router, openapi); @@ -480,7 +489,8 @@ fn build_operations(router: Router, openapi: &dyn OpenApiRegistry) -> Router { StatusCode::OK, "Metric definitions", ) - .standard_errors(openapi) + .error_401(openapi) + .error_500(openapi) .handler(metric_definitions::list_metric_definitions) .register(router, openapi); diff --git a/src/ingestion/tests/e2e/api/test_metric_results.py b/src/ingestion/tests/e2e/api/test_metric_results.py index afaa698c6..30ffa0d89 100644 --- a/src/ingestion/tests/e2e/api/test_metric_results.py +++ b/src/ingestion/tests/e2e/api/test_metric_results.py @@ -64,7 +64,7 @@ def test_metric_results_400_reversed_period(api) -> None: def test_metric_results_400_unknown_metric_key(api) -> None: """An unknown `metric_key` is resolved against the catalog and rejected as a 400 (`unavailable`) — NOT a 404. Pins that the compute endpoint has no - not-found path (the spec's declared 404 is `.standard_errors` boilerplate).""" + not-found path, which is why the spec declares no 404 for it.""" body = _request( metrics=[{"metric_key": "e2e.definitely-not-a-real-metric", "views": [{"view": "period"}]}], ) diff --git a/src/ingestion/tests/e2e/lib/api_coverage.py b/src/ingestion/tests/e2e/lib/api_coverage.py index 3900861eb..d9c240707 100755 --- a/src/ingestion/tests/e2e/lib/api_coverage.py +++ b/src/ingestion/tests/e2e/lib/api_coverage.py @@ -76,8 +76,6 @@ "POST /v1/admin/metric-thresholds": frozenset({404, 409}), # 404 boilerplate; 409=#1664 # persons 200/404 covered via the in-process Identity stub (#1691); rest boilerplate "GET /v1/persons/{email}": frozenset({400, 403, 409}), - # 404/409 boilerplate; 403 IS reachable (person outside the caller's visible set) - "POST /v1/metric-results": frozenset({404, 409}), # saved-query CRUD + run (#1965): 403 (no role gate — cross-tenant is 404 by # opacity) and 409 (no conflict path) are `.standard_errors` boilerplate. "GET /v1/queries": frozenset({400, 403, 404, 409}), # boilerplate: list, no input/lookup/conflict