---
id: w1/m2.5/t002
title: Extract internal/apps — read side + package skeleton
worker: worker1
status: done
estimate: 25m
depends_on: [w1/m2.5/t001]
---

## Objective

Stand up the `internal/apps` package with its **read** side and the shared helpers the whole feature uses: the `AppView` model + `view()` mapping, the `fetch`/`patch` primitives, and the read verbs (`List`, `Get`) with their REST/GraphQL/MCP registration fragments — plus read-path tests. The write verbs land in t003 into this same package.

## Context

- Source: `internal/api/core.go` (`AppView`, `view`, `fetch`, `patch`, `List`, `Get`) and the read slices of `rest.go` / `graphql.go` / `mcp.go`; tests in `api_test.go`.
- `patch` is the shared write primitive used by t003's verbs — create it here so the package skeleton (base wiring, gate, helpers) exists before the write side is added.
- Read fragments: REST `GET /v1/services` + `/v1/services/{id}`, GraphQL `services` + `server(id)` (the `Service` object type), MCP `list_services` + `get_service` — all registering into the single roots from t001.

## Steps

1. Create `internal/apps` with `service.go` (List/Get, each starting with the `authorize` gate), `models.go` (`AppView`, `view`), and the shared `fetch`/`patch` helpers.
2. Add `rest.go`/`graphql.go`/`mcp.go` read fragments registering into the shared roots.
3. Depend on `core` for base/gate/errors (`ErrNotFound`).
4. Move the List/Get + 404-mapping tests; remove the moved code from the old files.

## Files

- `lego/backend/internal/apps/{service.go,models.go,rest.go,graphql.go,mcp.go,*_test.go}`
- `lego/backend/internal/api/{core.go,rest.go,graphql.go,mcp.go}` (remove moved read code)

## Acceptance criteria

- [ ] `go build ./... && go test ./...` green.
- [ ] List/Get reachable and identical over REST, GraphQL, and MCP; unknown App ⇒ `ErrNotFound` (404) as before.
- [ ] The `Service` GraphQL type + `list_services`/`get_service` MCP tools register into the single roots.

## Out of scope

- The write verbs (Restart/Suspend/Resume) and single-writer wiring — t003.
