Cards specific to go. Use them with the level page that matches your input. Report each check as PASS, FAIL, or N/A with file:line evidence. A FAIL carries the card's severity. Any blockFAIL means request changes. A should-fix or discussFAIL goes in the review but does not block.
Verdict: request changes - change, function - 2 block, 1 should-fix FAIL, 1 PASS, 14 N/A
FAIL [block] chg-expand-contract - src/a.py:42 - renames the column and drops the old one in one migration
FAIL [block] svc-sqli-authn - src/db.py:88 - proven: builds the WHERE clause with an f-string from request.args
FAIL [should-fix] chg-one-concern - src/b.py:7 - a logging rewrite rides along with the bug fix
PASS chg-breaking-change-taxonomy - src/c.py:15 - no signature or return shape changes
N/A: 14 cards, applies_when does not hold
What the badges mean
blockmust be fixed before merge or release.
should-fixfix it, but it need not block.
discussraise it and decide together.
stablevetted; use for verdicts.
draftnot vetted; do not use for a verdict.
Tool gate: what a linter or CI check could enforce instead of a reviewer.
Draft cards
No stable cards yet.
7 draft cards
A draft card is not vetted. Report a FAIL of one under Draft findings, at should-fix at most, never in the ledger or the verdict. How a draft becomes stable
go-govulncheck-in-ci
should-fixdraftsecurity
Applies when: The repository is a Go module with a CI pipeline.
Rule. Run govulncheck ./... in CI and fail the build on a reported vulnerability that your code calls.
Why. Dependencies pick up known vulnerabilities after you pin them. A scan that only runs on a laptop finds them when someone remembers. govulncheck reports only vulnerabilities in functions your code reaches, so a failing run is worth acting on.
FAIL
jobs:
test:
steps:
- uses: actions/checkout@v4
- run: go test ./...
PASS
jobs:
test:
steps:
- uses: actions/checkout@v4
- run: go test ./...
- run: go run golang.org/x/vuln/cmd/govulncheck@latest ./...
Counterpoint. "A new advisory breaks an unrelated pull request." That is the signal; the scan needs a fix or a recorded exception. A scheduled run on the main branch keeps the check alive between pull requests.
Why it is a draft: too few organisations back a clause of the Rule. Only the Go team states it; needs two more organisations that run govulncheck in CI How a draft becomes stable
Applies when: A Go function makes an HTTP or other network call.
Rule. Network calls carry a deadline: a context.Context passed to NewRequestWithContext, or an http.Client with Timeout, never http.DefaultClient without either.
Why. A zero timeout means no timeout. One stalled peer hangs the goroutine, and with it the caller, until the process restarts.
Counterpoint. "Streaming bodies outlive any fixed timeout." Then set per-phase timeouts on the transport and use the context for the total deadline; keep the deadline.
Why it is a draft: too few organisations back a clause of the Rule. Cloudflare and the Go docs (Google) state it; a third independent organisation is missing How a draft becomes stable
Applies when: The repository is a Go module built in CI.
Rule. Commit go.sum, build in CI with -mod=readonly, and run go mod verify.
Why.go.sum pins the hash of every dependency, so a re-uploaded version fails the build. A build that rewrites go.mod on its own hides drift. go mod verify catches a tampered module cache.
FAIL
# go.sum is in .gitignore
- run: go mod tidy && go build -mod=mod ./...
PASS
- run: go mod verify
- run: go build -mod=readonly ./...
- run: go mod tidy -diff
Counterpoint. "The default is already readonly since Go 1.16." True for go build; the explicit flag and the go.sum check keep a stray GOFLAGS=-mod=mod from changing that.
Why it is a draft: too few organisations back a clause of the Rule. Only the Go team states it; needs two more organisations How a draft becomes stable
Rule.init() does no I/O, reads no environment and does not depend on other init() functions; do that work from main().
Why.init() runs on import, in an order readers do not see, before tests can set anything up. A network call or env read there makes importing the package a side effect.
FAIL
var db *sql.DB
func init() {
db, _ = sql.Open("postgres", os.Getenv("DATABASE_URL"))
}
Applies when: A Go module uses goroutines, channels or shared state and has CI.
Rule. CI runs the test suite with go test -race ./....
Why. Data races pass ordinary tests and fail in production, rarely and without a trace. The detector finds them only when the racing code runs under test, so the flag has to be on in the run that every change passes.
FAIL
- run: go test ./...
PASS
- run: go test -race ./...
Counterpoint. "The race detector slows tests and needs cgo." It costs several times the runtime and memory, so run it on every pull request if the suite is fast; otherwise at least on the main branch.
Why it is a draft: too few organisations back a clause of the Rule. Only the Go team states it; needs two more organisations How a draft becomes stable
Applies when: The repository is a Go module with a CI pipeline.
Rule. CI runs go vet and a linter set that includes staticcheck and errcheck, and a finding fails the build.
Why. These tools catch unchecked errors, misused Printf verbs and dead code before a reviewer sees them. If review comments repeat, the gate is missing. Lint the same way across the whole codebase; consistency matters more than the exact set.
FAIL
- run: go build ./... && go test ./...
PASS
- run: go vet ./...
- uses: golangci/golangci-lint-action@v6 # .golangci.yml enables errcheck, staticcheck
- run: go test ./...
Counterpoint. "A new linter floods an old codebase." Enable it with new-from-rev so only new code is held to it, then widen.
Why it is a draft: too few organisations back a clause of the Rule. Only Uber states it in a published guide; needs two more organisations How a draft becomes stable
Tool gate: go vet, staticcheck, errcheck via golangci-lint
Counterpoint. "%w makes the wrapped error part of my API." Right: callers may depend on it. Use %v at a package boundary when you do not want that, and say so.
Why it is a draft: too few organisations back a clause of the Rule. Go team and Uber state it; a third independent organisation is missing How a draft becomes stable