grpc-architect — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited grpc-architect (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Vanilla gRPC over HTTP/2 — backend-to-backend services. Pair with protobuf-architect for schema design. Go-specific implementation skeletons in RECIPES.md; pinned deps in STACK.md. Other languages follow the same protocol-level conventions with idiomatic substitutions.
One service per file, named after the resource. Methods are verb-noun, request and response are always typed messages — never raw primitives or google.protobuf.Empty as input. Example in RECIPES.md.
CreateUserResponse { User user = 1; } over returning User directly — leaves room to add fields without bumping the major version.ListUsersRequest { string cursor = 1; int32 limit = 2; } → ListUsersResponse { repeated User users = 1; string next_cursor = 2; }.status.Error with codesUse gRPC standard codes, return errors via status.Error(code, msg). Map domain errors to codes in one central place (skeleton in RECIPES.md).
| Code | Use for |
|---|---|
OK | success |
INVALID_ARGUMENT | request fails schema or business validation |
FAILED_PRECONDITION | request valid but system state forbids it (e.g. delete a non-empty resource) |
OUT_OF_RANGE | numeric / range-specific violation distinct from INVALID_ARGUMENT |
UNAUTHENTICATED | missing or invalid credentials |
PERMISSION_DENIED | authenticated but not authorized |
NOT_FOUND | resource doesn't exist |
ALREADY_EXISTS | unique-constraint or idempotency-key collision (with a different body) |
ABORTED | concurrency conflict (ETag-equivalent) — client should re-fetch and retry |
RESOURCE_EXHAUSTED | rate limit; per-tenant quota |
DEADLINE_EXCEEDED | the request didn't complete in time — set by the runtime |
UNAVAILABLE | transient — load-balancer drained, restart in progress; client retries |
INTERNAL | unexpected server-side failure — bug or external dependency error |
UNIMPLEMENTED | method exists in proto but server doesn't handle it (use during rollout) |
Don't reach for `INTERNAL` as a default. Map every known domain error to a specific code.
google.rpc.ErrorInfo, google.rpc.BadRequest) when clients need machine-readable error context — equivalent to REST's RFC 7807 (see rest-api-architect §7). Always include a correlation id.INTERNAL with the correlation id.rpc Ping(StringValue) returns (StringValue) — wrap in PingRequest / PingResponse.protovalidate (see protobuf-architect §5). Enforced server-side via an interceptor (§4).Interceptors are gRPC's middleware. Order matters — outermost first: recovery → request-id → log → auth → validation → metrics. Full chain in RECIPES.md.
INTERNAL with correlation id (never a stack trace).WithAuthFunc interceptor.validator.Validate(req) and returns INVALID_ARGUMENT with google.rpc.BadRequest details on failure.ChainStreamInterceptor. Streaming validation requires handling per-message in client/bidi streams.gRPC supports four call types. Pick the simplest one that meets the requirement.
| Pattern | Use for | Pitfalls |
|---|---|---|
| Unary | Default — request/response | None — start here |
| Server-stream | Server emits N responses to one request (event feeds, paginated downloads that don't fit one response, log tail) | Connection state outlives the request; resume tokens needed for restarts |
| Client-stream | Client uploads N messages, server returns one summary (large uploads, batch ingest) | Backpressure from server requires careful flow control |
| Bidi-stream | Genuinely interactive (chat, collaborative editing, control protocols) | Connection lifecycle complexity; reconnect / resume logic; deadlines |
start_after_id or a cursor in the request so a disconnected client can resume from a known point..proto comments; future-you will thank you.Every gRPC call has a deadline. Clients set; servers respect; downstream calls inherit the remaining time. Client skeleton in RECIPES.md.
ctx.Err() periodically in long-running handlers; abort work the moment the deadline fires.context.WithTimeout slightly less than the client deadline to leave headroom for response serialization.| Use metadata for | Use message fields for |
|---|---|
Auth tokens (authorization: Bearer ...) | Business data |
| Request IDs / correlation IDs (read by middleware) | Anything the handler reads as part of business logic |
Tracing context (traceparent) | — |
Rate-limit hints (x-tenant-id for routing) | — |
-bin suffix).x-request-id) — interceptor reads it on entry, injects into context, logs against it.Reflection enables grpcurl and IDE plugins to introspect the service without the .proto file — on in dev, off in production. It leaks the entire service surface. Skeleton in RECIPES.md. The health service (grpc.health.v1) is always on — load balancers and orchestrators need it.
bufconn for in-processThe google.golang.org/grpc/test/bufconn package gives an in-memory listener — full server + client without a real socket. Faster than net.Pipe, simpler than spinning up a test server on a port. Skeleton in RECIPES.md.
gRPC's wins are real but specific:
.proto is the canonical schema; clients in any language are generated. No OpenAPI drift.REST is the better default when:
curl works without tooling; OpenAPI is the universal documentation format.The two coexist: gRPC for east-west backend traffic, REST for north-south client-facing endpoints. Connect-RPC lets one set of .proto files serve gRPC, gRPC-Web, and Connect (browser-friendly) — worth considering as the upgrade path. grpc-gateway is an alternative for REST/JSON facades but adds spec complexity and error-translation discipline.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.