protobuf-architect — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited protobuf-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.
Language-agnostic schema standards. Proto files target proto3 + buf toolchain. Validation uses protovalidate (CEL). Code generation is per-language and out of scope here — see the language architect skill for the generated-code idioms (e.g. go-architect when generating for Go). File-layout, validation, codegen, and breaking-check snippets in RECIPES.md; pinned tool versions in STACK.md.
Buf-style hierarchical packages — <org>.<product>.<resource>.<version>. Mirrors the on-disk path. One service or coherent message group per file. Tree + package declaration in RECIPES.md.
acme/shop/users/v1/ → package acme.shop.users.v1;. Enforced by buf lint.optional keyword (proto3.15+) when "field absent" must be distinguishable from "field present with zero value" — common for PATCH-style partial updates.buf lint. The language plugin converts to the target idiom (Go CamelCase, Python snake_case, etc.).User, not Users (the collection is repeated User).UPPER_SNAKE_CASE prefixed with the enum name to keep them unambiguous across imports. Example in RECIPES.md.optional instead — it's the modern equivalent and doesn't require importing wrappers.proto.repeated KeyValue with explicit key/value fields gives you ordering, validation, and the ability to add metadata per entry later.reserved it forever (example in RECIPES.md).int32 age = 5; to string age = 5; is a breaking change at the wire level. Delete + reserve + introduce a new field with a new number instead.acme.shop.users.v1), never appended to message names (UserV1 is wrong).v1/ and v2/ coexist; clients migrate at their pace.[deprecated = true] on the field; communicate via Deprecation headers when wrapped in REST; remove only in the next major version after migration is complete.protovalidate (CEL)Buf's protovalidate is the modern, declarative replacement for the older protoc-gen-validate (PGV). Constraints are CEL expressions attached as field options; validation runs at runtime via per-language protovalidate libraries. Field-level and cross-field examples in RECIPES.md.
(buf.validate.message).cel.buf generate + buf.gen.yamlOne config file at the repo root drives all generators. Versions of the plugins are pinned in buf.gen.yaml itself; no protoc invocation by hand. Full config in RECIPES.md.
buf themselves. Commit it under gen/<lang>/... clearly separated from hand-written source.buf.gen.yaml — never :latest.buf lintbuf lint runs the STANDARD rule set out of the box (proto3 conventions, naming, file structure). Add to CI. buf.yaml config in RECIPES.md.
Common lint catches:
snake_case*_UNSPECIFIED = 0option *_packagebuf breaking in CIbuf breaking --against '.git#branch=main,subdir=proto' blocks merges that introduce breaking changes without an intentional new vN package. FILE-level rules (the default) treat the file as the unit of compatibility — appropriate when generated code is consumed file-by-file. Stricter PACKAGE and WIRE modes exist; pick FILE unless you have a reason to differ.
--against '.git#tag=v1.5.0,subdir=proto'.Use the Google-provided well-known types instead of inventing equivalents.
| Use case | Type |
|---|---|
| Point-in-time timestamp | google.protobuf.Timestamp (RFC 3339, nanosecond precision) |
| Duration | google.protobuf.Duration |
| Wall-clock date (no time) | google.type.Date (from googleapis) |
| Money | google.type.Money (from googleapis) — currency code + amount |
| Unstructured JSON | google.protobuf.Struct (only for genuinely schemaless payloads) |
| Empty response | google.protobuf.Empty |
| Optional field marker | proto3 optional keyword (no wrapper needed) |
| Field mask for partial updates | google.protobuf.FieldMask |
When two services need the same domain concept (Money, Address, CustomerId), put it in a shared types/v1/ sub-package — example layout in RECIPES.md.
Address messages might genuinely have different semantics; force the sharing only when the model is provably the same.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.