From argos
gRPC + Protobuf proto3 disipline — schema (field number + reserved + well-known types), 4 call types (unary/server-stream/client-stream/bidi), deadline propagation, gRPC status code + rich error details, schema evolution (buf breaking), metadata + interceptors (auth/log/trace), mTLS, LB (client-side/proxy/xDS), streaming backpressure, grpc-gateway (REST), grpc-web (browser) ve Connect, reflection.
npx claudepluginhub resultakak/argos --plugin argosThis skill uses the workspace's default tool permissions.
`agents/shared/severity-rubric.md` ve `agents/shared/escalation-matrix.md`
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
agents/shared/severity-rubric.md ve agents/shared/escalation-matrix.md
default-load sayılır (agents/coordination.md §11). Bu skill'in çıktısı
Critical / High / Medium / Low + kanıt formatında olmak zorunda — spekülatif
Critical yasak. Sahiplik dışı bulgu ilgili agent'a delege; karar yetkisi eşiği
aşılırsa kullanıcı onayı zorunlu.
buf breaking CI gate.syntax = "proto3";
package acme.orders.v1;
option go_package = "github.com/acme/proto/orders/v1;ordersv1";
import "google/protobuf/timestamp.proto";
message Order {
string id = 1;
string user_id_hash = 2;
int64 total_amount_minor = 3;
Currency currency = 4;
repeated LineItem items = 5;
google.protobuf.Timestamp created_at = 6;
reserved 7 to 10;
reserved "legacy_field";
}
enum Currency {
CURRENCY_UNSPECIFIED = 0;
CURRENCY_TRY = 1;
CURRENCY_USD = 2;
CURRENCY_EUR = 3;
}
service OrderService {
rpc GetOrder(GetOrderRequest) returns (Order);
rpc ListOrders(ListOrdersRequest) returns (stream Order);
}
# buf.yaml
version: v1
modules:
- path: proto/orders/v1
lint:
use: [DEFAULT, PACKAGE_VERSION_SUFFIX]
breaking:
use: [PACKAGE, FILE, WIRE, WIRE_JSON]
# buf.gen.yaml
version: v1
plugins:
- plugin: buf.build/protocolbuffers/go
out: gen/go
- plugin: buf.build/grpc/go
out: gen/go
- plugin: buf.build/grpc-ecosystem/gateway
out: gen/go
buf generate
buf lint
buf breaking --against ".git#branch=main" # CI gate
func (s *server) GetOrder(ctx context.Context, req *pb.GetOrderRequest) (*pb.Order, error) {
// ctx zaten client deadline; downstream'e aynı ctx
order, err := s.repo.FindOrder(ctx, req.OrderId)
if errors.Is(err, ErrNotFound) {
return nil, status.Errorf(codes.NotFound, "order %s not found", req.OrderId)
}
if err != nil {
return nil, status.Errorf(codes.Internal, "repo error: %v", err)
}
user, err := s.userClient.GetUser(ctx, &userpb.GetUserRequest{Id: order.UserId})
...
return toProto(order, user), nil
}
Asla context.Background() chain'de: deadline sızıntı.
serviceConfig := `{
"loadBalancingConfig": [{"round_robin": {}}],
"methodConfig": [{
"name": [{"service": "acme.orders.v1.OrderService"}],
"retryPolicy": {
"maxAttempts": 3,
"initialBackoff": "0.1s",
"maxBackoff": "1s",
"backoffMultiplier": 2.0,
"retryableStatusCodes": ["UNAVAILABLE"]
}
}]
}`
conn, _ := grpc.NewClient(
"dns:///orders.acme.local:50051",
grpc.WithTransportCredentials(credentials.NewTLS(tlsCfg)),
grpc.WithDefaultServiceConfig(serviceConfig),
)
client := pb.NewOrderServiceClient(conn)
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
resp, err := client.GetOrder(ctx, &pb.GetOrderRequest{OrderId: id})
// auth + logging + trace + metrics
s := grpc.NewServer(
grpc.ChainUnaryInterceptor(
recoveryInterceptor,
loggingInterceptor,
tracingInterceptor,
metricsInterceptor,
authInterceptor,
),
grpc.ChainStreamInterceptor(
recoveryStreamInterceptor,
loggingStreamInterceptor,
tracingStreamInterceptor,
metricsStreamInterceptor,
authStreamInterceptor,
),
)
OpenTelemetry: otelgrpc.NewServerHandler() + otelgrpc.NewClientHandler().
import "google.golang.org/genproto/googleapis/rpc/errdetails"
st := status.New(codes.FailedPrecondition, "Idempotency key already used")
det, _ := st.WithDetails(&errdetails.PreconditionFailure{
Violations: []*errdetails.PreconditionFailure_Violation{{
Type: "IDEMPOTENCY",
Subject: "order-" + req.OrderId,
Description: "key reused within 24h",
}},
})
return nil, det.Err()
Client side:
if err != nil {
st, _ := status.FromError(err)
for _, d := range st.Details() {
switch x := d.(type) {
case *errdetails.PreconditionFailure:
// structured retry logic
}
}
}
serverCert, _ := tls.LoadX509KeyPair("server.crt", "server.key")
caBytes, _ := os.ReadFile("ca.crt")
caPool := x509.NewCertPool()
caPool.AppendCertsFromPEM(caBytes)
s := grpc.NewServer(grpc.Creds(credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{serverCert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: caPool,
MinVersion: tls.VersionTLS13,
})))
Mesh (Istio/Linkerd) + SPIFFE/SPIRE → otomatik mTLS (uygulamada
WithTransportCredentials(insecure) mesh içi OK, mesh dışı yasak).
func (s *server) ListOrders(req *pb.ListOrdersRequest, stream pb.OrderService_ListOrdersServer) error {
iter := s.repo.IterOrders(stream.Context(), req)
defer iter.Close()
for iter.Next() {
if err := stream.Send(iter.Order()); err != nil {
return err
}
select {
case <-stream.Context().Done():
return stream.Context().Err()
default:
}
}
return iter.Err()
}
HTTP/2 flow control window tune:
grpc.NewServer(
grpc.InitialWindowSize(1<<20), // 1MB
grpc.InitialConnWindowSize(1<<20),
grpc.MaxRecvMsgSize(16<<20), // 16MB
grpc.MaxSendMsgSize(16<<20),
)
import "google/api/annotations.proto";
service OrderService {
rpc GetOrder(GetOrderRequest) returns (Order) {
option (google.api.http) = { get: "/v1/orders/{order_id}" };
}
rpc CreateOrder(CreateOrderRequest) returns (Order) {
option (google.api.http) = { post: "/v1/orders" body: "*" };
}
}
Buf plugin: buf.build/grpc-ecosystem/gateway → *.pb.gw.go runtime.
Browser native gRPC yok (HTTP/2 trailers). Çözümler:
connectrpc.com) — HTTP/1.1 + HTTP/2 + 3 protokol;
browser native; bundle ~10KB// Connect-go server (gRPC + Connect protocol aynı handler)
import "connectrpc.com/connect"
api := connect.NewServer(...)
mux := http.NewServeMux()
mux.Handle(ordersv1connect.NewOrderServiceHandler(impl))
if os.Getenv("ENV") != "production" {
reflection.Register(s)
}
grpcurl localhost:50051 list
grpcurl localhost:50051 describe acme.orders.v1.OrderService
grpcurl -d '{"order_id": "..."}' localhost:50051 acme.orders.v1.OrderService/GetOrder
grpc.NewServer(
grpc.KeepaliveParams(keepalive.ServerParameters{
MaxConnectionIdle: 5 * time.Minute,
MaxConnectionAge: 30 * time.Minute,
MaxConnectionAgeGrace: 5 * time.Second,
Time: 30 * time.Second,
Timeout: 10 * time.Second,
}),
grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
MinTime: 10 * time.Second,
PermitWithoutStream: true,
}),
)
buf.yaml lint + breaking configbuf lint + buf breaking --against mainvN suffixCURRENCY_UNSPECIFIED = 0 enum defaultctx chain)google.rpc.Status)UNAVAILABLE retryable)otelgrpc instrumentationcontext.Background() chain).WithInsecure() non-local.buf breaking yok CI'da.User: /grpc-review orders-svc
Agent (api-contract-guardian + backend-implementer + security-reviewer):
1. Proto inventory: 12 service, 87 message, 28 enum.
2. Field number audit: 2 service field reuse history (`OrderStatus.PENDING = 1`
→ `= 2` git log'unda; wire format catastrophe risk).
3. Reserved usage: 8 message reserved kullanıyor; 4 değil (remove'de drift
riski).
4. Deadline propagation: 2 RPC `context.Background()` chain (timeout sızıntı).
5. Status code: 6 RPC `INTERNAL` generic; `NOT_FOUND` / `PERMISSION_DENIED`
kullanılmıyor.
6. CI: `buf lint` yok; `buf breaking` yok.
7. mTLS: dev `WithInsecure()` 3 servis production'da.
8. Reflection production enabled.
9. Retry policy: 5 client retryable status code config eksik.
10. Streaming: 1 server-stream backpressure check yok.
Findings:
- Critical: Field number reuse history (revert tag + freeze)
- Critical: Reflection production enabled
- Critical: 3 servis production WithInsecure (mTLS yok)
- High: Deadline propagation 2 RPC kırık
- High: buf lint + breaking CI gate yok
- High: Status code INTERNAL generic 6 RPC
- Medium: Reserved kullanmayan message 4 (future remove riski)
- Medium: Streaming backpressure check yok
Action items: 8 issue
# gRPC Audit: <service>
## Proto inventory + buf workspace
## Schema audit
- Field number history (reuse riski)
- Reserved usage
- Enum UNSPECIFIED = 0 default
- Well-known types
## Deadline propagation
## Status code rubric
## Interceptor chain
## mTLS + TLS
## Retry policy + LB
## Streaming backpressure
## grpc-gateway / grpc-web / Connect
## Findings (Critical/High/Medium/Low)
## Action Items
| P | Aksiyon | Sahip | Bitiş |