# Starter and Essential Loki Routing Design

## Purpose

`clinic loki query --cluster-id <id>` currently sends every request to the
logical-cluster compatibility endpoint at
`/data-proxy/loki/{clusterID}/api/v1/query_range`. Starter and Essential
clusters run in shared regional infrastructure, so platform logs such as
`tidb-serverless` DM worker and master logs are not visible through that
logical-cluster route.

After this change, exact Starter and Essential clusters use Clinic's canonical
regional system-log datasource route. Users can run the same explicitly scoped
LogQL they use in the Loki UI while continuing to select the TiDB Cloud cluster
with `--cluster-id`.

## Scope

The change applies only to `clinic loki query` and only when normalized
`clusterDeployTypeV2` is exactly `starter` or `essential`.

The following behavior remains unchanged:

- `essential v2` and `essential v2 resource pool` continue through the current
  Premium-style logical-cluster route.
- Premium, BYOC, Dedicated, and all other deploy types continue through the
  existing route and namespace inference.
- `loki instance-map`, `loki labels`, `loki label-values`, and `diagnose` remain
  unchanged because the available logical cluster metadata cannot safely scope
  their regional operations to one physical pool.

## Routing Design

For exact Starter or Essential clusters, the query command performs these
steps:

1. Resolve cluster metadata using the existing cluster-reference flow.
2. Hydrate Starter/Essential routing metadata from the Dashboard cluster API
   even when the initial reference came from a selected profile. Read
   `clusterProviderName`, `clusterRegionName`, and `clusterDeployTypeV2` from
   the exact cluster-ID response and retain provider and region only in the
   ephemeral cluster reference. Do not persist new profile fields.
3. Require the LogQL to contain exactly one stream selector and require that
   selector to contain a non-empty equality matcher of the form
   `cluster="physical-cluster-name"`. Reject missing selectors, `{}`, omitted
   LogQL, multiple selectors, empty values, regex matchers, and negative
   matchers. A regional datasource contains multiple physical clusters, so a
   query that is absent or potentially broad must fail before any log or
   datasource-catalog request is sent.
4. Fetch `/data-proxy/api/v1/system-log-datasources` and select exactly one
   datasource whose provider and region match the cluster metadata
   case-insensitively. The expected response is
   `{"status":"success","data":{"datasources":[...]}}`; each candidate uses
   the `uid`, `provider`, and `region` fields. The matched `uid` must be
   non-empty.
5. Send the range request to
   `/data-proxy/api/v1/system-log-datasources/{escapedUID}/logs/query-range`.
6. Preserve current time parsing, limit, direction, output, retry, and selector
   augmentation behavior. Missing `cluster_env` is still injected. Missing
   namespace is injected as `namespace="tidb-serverless"` unless
   `--skip-namespace-injection` is set.

No request may silently fall back to the logical-cluster Loki route after the
Starter or Essential predicate selects regional routing.

## Error Handling

Routing fails closed with a descriptive error when provider or region is
missing, the LogQL is omitted, the LogQL lacks exactly one safely scoped
equality `cluster` matcher, the datasource catalog is malformed, the matched
datasource UID is empty, the catalog has no provider/region match, or the
catalog has multiple matches. Errors must include the cluster ID and the
missing or ambiguous routing identity without printing credentials. No
query-range request is sent after any routing or catalog validation failure.

Existing Clinic HTTP errors remain inspectable through ordinary error wrapping.
The current query-range retry behavior remains unchanged and retries the same
regional request.

## Code Boundaries

Keep datasource-catalog parsing and route selection in a focused Loki routing
unit under `internal/cmd/`. `internal/cmd/loki.go` continues to own Cobra command
behavior, time/query parameters, output parsing, and retries. Cluster metadata
resolution retains provider and region only in the internal ephemeral
`clusterReference` type. The Starter/Essential route resolver must explicitly
refresh Dashboard metadata rather than accepting a profile-only reference that
lacks these ephemeral fields.

Update `README.md`, `docs/COMMAND_SURFACE.md`, and
`skills/clinic-cli/SKILL.md` so the non-obvious tier-specific route and explicit
physical-cluster requirement are visible to users and agents. Update Cobra help
and its tests to state that omitted LogQL and `{}` remain supported for other
tiers but are rejected for Starter/Essential regional routing.

## Testing

Implementation follows red-green-refactor. Tests must first demonstrate the
missing behavior, then cover:

- exact Starter and Essential routing through the regional datasource;
- case-insensitive provider and region matching;
- rejection of omitted LogQL, `{}`, missing physical `cluster` matchers,
  negative/regex/broad cluster matchers, and multi-selector expressions;
- selected-profile routing that refreshes provider and region without
  persisting them;
- missing provider, missing region, malformed catalog, empty UID, missing
  datasource, and ambiguous datasource failures with no logical-route fallback
  or query-range request;
- preservation of `cluster_env`, `tidb-serverless` namespace injection, and
  `--skip-namespace-injection`;
- unchanged Essential V2, Essential V2 resource pool, and Premium paths and
  selectors;
- unchanged output parsing and 504 retry behavior on the regional route.

Repository acceptance requires focused Loki tests followed by `make verify`.
