---
description: Go gRPC service conventions
globs: ["**/*.go","proto/**/*.proto","buf.yaml","buf.gen.yaml"]
alwaysApply: false
---

# Go gRPC

- Protos live in `proto/<pkg>/v1/*.proto` with `package acme.orders.v1;` and `option go_package`. Generate with `buf generate`; lint with `buf lint`; check compatibility with `buf breaking --against '.git#branch=main'`.
- Never edit generated `*.pb.go` files. Never reuse or renumber field numbers; mark removed ones `reserved`.
- RPC names are verbs (`CreateOrder`) with dedicated `CreateOrderRequest`/`CreateOrderResponse` messages, even if they look empty today.
- Server types embed `UnimplementedXServer` for forward compatibility.
- Return errors with `status.Error(codes.NotFound, "order not found")`; map domain errors in one place. Never return raw internal errors to clients. Use `errdetails` for field violations.
- Always respect `ctx`: pass it to DB/HTTP calls, check `ctx.Err()` in long loops. Clients set deadlines on every call (`context.WithTimeout`).
- Cross-cutting concerns as interceptors (logging, auth, recovery, metrics), chained with `grpc.ChainUnaryInterceptor`.
- Validate requests with `protovalidate` annotations if the project uses them, otherwise explicit checks at the top of each handler.
- Register health (`grpc_health_v1`) and reflection only in non-production builds unless needed.

## Done when
`buf lint`, `buf breaking`, `go vet ./...`, and `go test -race ./...` pass; tests use `bufconn` for an in-memory server.
