# Public Metrics Forbidden-Metric Filtering

## Background

The public metrics aliases expose Prometheus-compatible `query_range` and
`series` APIs. A set of infrastructure and cost metrics must not be readable
through those public endpoints.

## Target behavior

Only the following public GET endpoints are filtered:

- `/api/v1/orgs/{org_id}/data-proxy/metrics/{cluster_id}/query_range`
- `/api/v1/orgs/{org_id}/data-proxy/metrics/{cluster_id}/series`

After the existing public request validation, ownership check, and target
resolution succeed, a valid query that references any forbidden metric returns
an HTTP 200 Prometheus success response without contacting the metrics
upstream. `query_range` returns an empty matrix and `series` returns an empty
array. Legacy and private canonical metrics routes retain their current
behavior.

Invalid PromQL continues to follow the existing error path. Metric matching
uses the PromQL parser and covers vector selectors, nested functions and
aggregations, label selectors, `__name__` selectors, and any `match[]` value.

## Implementation and compatibility

- Keep the forbidden metric names in one deduplicated set.
- Add public-route-specific filtering in the canonical metrics handler so the
  existing service and non-public routes are unchanged.
- Reuse the existing Prometheus empty-result response shapes.
- Do not change API schemas, authentication, ownership validation, or upstream
  routing for allowed queries.

## Test plan

- Verify blocked `query_range` and `series` requests return the correct empty
  response shape and do not call the upstream.
- Cover nested PromQL, labels, `__name__`, and multiple `match[]` selectors.
- Verify allowed metrics are forwarded and invalid PromQL retains the current
  error behavior.
- Verify legacy/private canonical routes are not affected.

## Release boundary

The change belongs to the `clinic_data_service` module and produces the
`clinic/data-service` image. The required deployment component is
`clinic-data-service`; no app-delivery configuration change is expected.
