---
id: w5/m7/t001
title: "GraphQL instanceTypes catalog query (id, name, cpu, memory) from lego/types/tiers"
worker: worker5
status: done
estimate: 30m
depends_on: []
---

## Objective

Expose the compute tier catalog over GraphQL so the picker renders real catalog data — never a hardcoded frontend copy (the ladder already existed in three places before w1/m8 collapsed it; the dashboard must not become the fourth).

## Context

- Catalog: `lego/types/tiers` (`tiers.Compute` — `IDs()`, `ByID`, per-tier `RenderPlan`/`CPU`/`Memory`). No prices exist and none may be added (Metronome decision, `store/api.go`).
- Feature home: the `apps` feature (`lego/backend/internal/apps/graphql.go`) already carries the service `plan` field and `updateServicePlan` mutation — the catalog read sits beside them. Query shape suggestion: `instanceTypes { id name cpu memory }` where `id` is the Render plan spelling (what `updateServicePlan` accepts, e.g. `pro_plus`) and `name` a display name derived from the internal id (e.g. "Pro Plus" from `pro-plus`); cpu/memory as the catalog's quantity strings — the frontend formats them ("0.5 CPU", "512 MB").
- This is a **bex extension** (Render's dashboard hardcodes its picker; no public equivalent), marked as such in a comment like the `updateServicePlan` precedent. Authz: reads are `core.RelCanView`; the query needs a service/verb home that keeps `TestAuthzGuardsEveryVerb` satisfied — a Service method (e.g. `InstanceTypes(ctx)`) with the guard, even though the data is static.
- Three-adapter parity note: deliberately GraphQL-only (recorded in the milestone README's Render-deltas) — document the omission in the fragment comment rather than adding REST/MCP surface nobody consumes.

## Steps

1. Add `Service.InstanceTypes(ctx)` (authz-guarded) returning the catalog projection.
2. Add the `instanceTypes` GraphQL query field + type to the apps fragment.
3. Backend tests: field shape, authz guard picked up by the sweep, values match `tiers.Compute`.

## Files

- `lego/backend/internal/apps/service.go`, `lego/backend/internal/apps/graphql.go` (+ tests)

## Acceptance criteria

- [ ] `{ instanceTypes { id name cpu memory } }` returns the 7 catalog tiers in ladder order, ids in Render spelling.
- [ ] `TestAuthzGuardsEveryVerb` covers the new verb; backend tests green.
- [ ] No tier values exist anywhere in `dashboard/src` after t003 lands (grep guard).

## Out of scope

- REST/MCP exposure; prices; postgres-family tiers (no Database UI yet).
